If you are unhappy with the direction of Ruby 1.8.7+, respond

Hi –

On Sat, 14 Feb 2009, Rick DeNatale wrote:

Sometime after that discussion, Matz, who I know has much more than a basic
understanding of hash-tables, decided that, yes,
defining the iteration order of Ruby hashes to be by insertion order, and
that this was easily done with minimal impact to performance/space
requirements by linking buckets in the internal hash table used to IMPLEMENT
Hash, and made this change in Ruby 1.9, which has been backported to Ruby
1.8.7.

Hashes aren’t ordered in 1.8.7, though.

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (The Well-Grounded Rubyist)

http://www.wishsight.com => Independent, social wishlist management!

On Fri, Feb 13, 2009 at 4:53 AM, William J. [email protected]
wrote:

incompatibility.

No, it’s not a gray area. Anyone who has a basic understanding of
hash-tables doesn’t even think about the iteration order.

Let me try to calm the waters on this particular part of the
conversation.

A couple of years ago, there was a long discussion here, when some, led
by
Hal F. IIRC, advocated defining the order for enumerating Ruby
hashes.

At that time, I argued vehemently to your point that hash tables are
inherently unordered, and therefore it was inconceivable to order them.

I was wrong.

First, although Ruby Hash is implemented using a hash table, they aren’t
hash tables, they are Ruby objects which for better or worse are named
simply Hash. Perhaps if they had been named something like Dictionary,
or
Map, a name which doesn’t betray the implementation, this all would have
been less controversial.

Sometime after that discussion, Matz, who I know has much more than a
basic
understanding of hash-tables, decided that, yes,
defining the iteration order of Ruby hashes to be by insertion order,
and
that this was easily done with minimal impact to performance/space
requirements by linking buckets in the internal hash table used to
IMPLEMENT
Hash, and made this change in Ruby 1.9, which has been backported to
Ruby
1.8.7.

And as for whether or not changing something which was previously
undefined
to something which is defined introduces a backwards compatibility
issue, I
think it’s pretty clear that it does not.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale

On Thu, Feb 12, 2009 at 10:24 PM, Urabe S.
[email protected] wrote:

Alex F. wrote:

We know the Rails issue (and solved), but could you elaborate on
issues with wxRuby and SWIG?

http://sourceforge.net/tracker2/?func=detail&aid=2034216&group_id=1645&atid=101645

This is not our fault. Please hold on and think yourself. GC is running means
ruby interpreter is running out of memory. It is as clear as day that object
allocation during GC is not doable, because we do not have any memory space.

GC is running may mean the interpreter is running out of memory, it
may mean some code just called GC.start for some other reason.

Hi –

On Sat, 14 Feb 2009, James C. wrote:

that this was easily done with minimal impact to performance/space
order does not work. Actually let me be more specific. My code was relying
on keys being inserted in the order they appear in a hash literal, and on
subsequent iteration occuring in the same order.

That doesn’t happen in any 1.8 version, though. (Sorry; I feel like
something’s going right past me, and I’ll stop after this iteration
:slight_smile:

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (The Well-Grounded Rubyist)

http://www.wishsight.com => Independent, social wishlist management!

2009/2/13 David A. Black [email protected]

IMPLEMENT
Hash, and made this change in Ruby 1.9, which has been backported to Ruby
1.8.7.

Hashes aren’t ordered in 1.8.7, though.

Seconded – 1.8.7 is precisely where my code that was relying on
insertion
order does not work. Actually let me be more specific. My code was
relying
on keys being inserted in the order they appear in a hash literal, and
on
subsequent iteration occuring in the same order. My own code was
maintaining
key order explicitly using an array of keys (
packr/lib/packr/collection.rb at 3.1 · jcoglan/packr · GitHub), but
when
using a hash literal to initialize an instance, the keys are not
inserted in
literal appearance order in 1.8.7.

So it may be that 1.8.7 does use insertion order for iteration, but does
not
use literal appearance order when creating a new hash.

In article
[email protected],
James C. [email protected] writes:

Regardless of whether they’re supposed to, the Rubies I’ve used before
1.8.7 actually do iterate in insertion order. Could be machine/OS specific,
a fluke, whatever. The point is that 1.8.7 definitely does not iterate in
the order that keys appear in a literal, at least on my machine. If this is
supposed to now be defined behaviour I’ll investigate further and file a bug
if necessary.

Would you show us an example which the insertion order is
preserved on 1.8.6 and not preserved on 1.8.7?

I tested as follows. The order is changed since 1.9.
1.8.7 is same as 1.8.6 and older.

% all-ruby -e ‘h = {2=>“b”, 1=>“a”}; p h’
ruby-1.4.6(2000-08-16) {1=>“a”, 2=>“b”}
ruby-1.6.0(2000-09-19) {1=>“a”, 2=>“b”}
ruby-1.6.1(2000-09-27) {1=>“a”, 2=>“b”}
ruby-1.6.2(2000-12-25) {1=>“a”, 2=>“b”}
ruby-1.6.3(2001-03-19) {1=>“a”, 2=>“b”}
ruby-1.6.4(2001-06-04) {1=>“a”, 2=>“b”}
ruby-1.6.5(2001-09-19) {1=>“a”, 2=>“b”}
ruby-1.6.6(2001-12-26) {1=>“a”, 2=>“b”}
ruby-1.6.7(2002-03-01) {1=>“a”, 2=>“b”}
ruby-1.6.8(2002-12-24) {1=>“a”, 2=>“b”}
ruby-1.8.0(2003-08-04) {1=>“a”, 2=>“b”}
ruby-1.8.1(2003-12-25) {1=>“a”, 2=>“b”}
ruby-1.8.2(2004-12-25) {1=>“a”, 2=>“b”}
ruby-1.8.3(2005-09-21) {1=>“a”, 2=>“b”}
ruby-1.8.4(2005-12-24) {1=>“a”, 2=>“b”}
ruby-1.8.5(2006-08-25) {1=>“a”, 2=>“b”}
ruby-1.8.5p52(2007-06-07) {1=>“a”, 2=>“b”}
ruby-1.8.5p113(2007-09-23) {1=>“a”, 2=>“b”}
ruby-1.8.5p115(2008-03-03) {1=>“a”, 2=>“b”}
ruby-1.8.5p231(2008-06-20) {1=>“a”, 2=>“b”}
ruby-1.8.5head(2008-06-20p231) {1=>“a”, 2=>“b”}
ruby-1.8.6p0(2007-03-13) {1=>“a”, 2=>“b”}
ruby-1.8.6p36(2007-06-07) {1=>“a”, 2=>“b”}
ruby-1.8.6p110(2007-09-23) {1=>“a”, 2=>“b”}
ruby-1.8.6p111(2007-09-24) {1=>“a”, 2=>“b”}
ruby-1.8.6p114(2008-03-03) {1=>“a”, 2=>“b”}
ruby-1.8.6p230(2008-06-20) {1=>“a”, 2=>“b”}
ruby-1.8.6p287(2008-08-11) {1=>“a”, 2=>“b”}
ruby-1.8.6head(2009-02-13p330) {1=>“a”, 2=>“b”}
ruby-1.8.7p0(2008-05-31) {1=>“a”, 2=>“b”}
ruby-1.8.7p17(2008-06-09) {1=>“a”, 2=>“b”}
ruby-1.8.7p22(2008-06-20) {1=>“a”, 2=>“b”}
ruby-1.8.7p72(2008-08-11) {1=>“a”, 2=>“b”}
ruby-1.8.7head(2009-02-13p116) {1=>“a”, 2=>“b”}
ruby-1.8(2009-02-05r22080) {1=>“a”, 2=>“b”}
ruby-1.9.1p0(2009-01-30r21907) {2=>“b”, 1=>“a”}
ruby-1.9(2009-02-11r22240) {2=>“b”, 1=>“a”}

something’s going right past me, and I’ll stop after this iteration
:slight_smile:

Regardless of whether they’re supposed to, the Rubies I’ve used before
1.8.7 actually do iterate in insertion order. Could be machine/OS
specific,
a fluke, whatever. The point is that 1.8.7 definitely does not iterate
in
the order that keys appear in a literal, at least on my machine. If this
is
supposed to now be defined behaviour I’ll investigate further and file a
bug
if necessary.

2009/2/13 James C. [email protected]:

something’s going right past me, and I’ll stop after this iteration
:slight_smile:

Regardless of whether they’re supposed to, the Rubies I’ve used before
1.8.7 actually do iterate in insertion order.

NO THEY DO NOT. It is the nature of a regular hashtable that
the order of entries in its internal data structures depends
only on the hash function and its inputs. It doesn’t know
anything about the order of entries in your hash literal.

I’ve shown you examples using Ruby 1.8.6 that clearly
demonstrate that it gives a **** about order of appearance
in a literal, or insertion order.

Stefan

Hi –

On Sat, 14 Feb 2009, James C. wrote:

something’s going right past me, and I’ll stop after this iteration
:slight_smile:

Regardless of whether they’re supposed to, the Rubies I’ve used before
1.8.7 actually do iterate in insertion order. Could be machine/OS specific,
a fluke, whatever. The point is that 1.8.7 definitely does not iterate in
the order that keys appear in a literal, at least on my machine. If this is
supposed to now be defined behaviour I’ll investigate further and file a bug
if necessary.

I think it probably is machine-dependent, or something like that. I’ve
never heard of hash order being anything but “not guaranteed” before
1.9 – except that if you iterate twice, I believe it definitely
happens in the same order both times (though I’m not 100% sure that
that’s actually specified or guaranteed either).

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (The Well-Grounded Rubyist)

http://www.wishsight.com => Independent, social wishlist management!

Hi Matz, I’m glad to see that you’ve entered this fray.

I trust that you know me well enough to know, that while I have strong
opinions, I have no ill-will, particularly to you or your language.

On Fri, Feb 13, 2009 at 3:10 AM, Yukihiro M.
[email protected]wrote:

as I understand, they both contain bugs that haven’t disclosed for
1.8.6 by accident.

I consider them minor and not being worse than previous releases.
Most of them are addressed already. Am I missing something?

First, the next comment is directed to a subset of the Ruby community,
which doesn’t include you Matz,

I know that Rails isn’t liked by everyone in the Ruby community, but for
better or worse, it’s an important factor to the health of a significant
portion of ‘our’ community. Those who don’t use Rails or other large
Ruby
frameworks over time haven’t experienced how we got to the point where
these
problems have been addressed.

At this point, it’s a little hard to recover the history, but, although
Rails 2.2 is now compatible with Ruby 1.8.7 it has taken work, and new
releases, from both the Ruby team and the Rails team.

Rails users faced with upgrades, need to deal with the evolution of both
Ruby and Rails. To a large extent Rails over the last year to 18 months
has
been even more volatile than Ruby. Porting a Rails app from Rails 1.2.x
to
Rails 2.0 (There was no Rails 1.3) was, as the change in major version
number indicates a fairly significant jump. And Rails made changes in
Rails
2.2 which, for applications doing certain complex things with
ActiveRecord,
VERY difficult to port. That’s not Ruby’s fault, it’s just a fact of
life.

So there are quite a few Rails Apps, which need to stay on a version of
Rails which is compatible with Ruby 1.8.6, but won’t work with Ruby
1.8.7.

|Back then nobody stepped up and said that if code working on 1.8.6

|broke it is a bug so I just left it at that - the compatibility seemed
|to be not so great.

Of course, none of us is perfect, particularly without the benefit of
hindsight.

As a practitioner and advocate of agile techniques, I like to have a
comprehensive test suite to expose compatibility issues when changes are
made.

Unfortunately in the case of a language like Ruby, it’s impossible to
have
such a test suite, It would need to draw from a significant portion of
the
applications implemented in Ruby, and applications implemented on
frameworks
like Rails which are implemented on Ruby, etc. etc. Not really
practical.

If compatibility of 1.8.7 is really “not so great”:

  • if it is fixable, we can fix.

  • if it is minor, we can upgrade 1.8.7 (or later) whenever we want,
    as we did in the past.

  • if upgrading is not affordable for enterprisey people (yes, I
    understand them; upgrading is costly even when incompatibility is
    minor),

I’m not sure who you are calling enterprisey people here. I know that
you
have no intent to disparage, but that term does carry a certain meaning
of
“the other guys” with some of the Rubyists, (and others) I run into.

To me “enterprisey” means someone working in a large corporate
enterprise,
who is following strategies, architectures and standards, promulgated by
enterprise vendors, like Microsoft, and IBM (to the extent IBM still has
the
influence to do this), probably because of edicts handed down from on
high
from the executives who play golf with sales reps from those vendors.

I’m pretty sure that such “enterprisey” types make up a very small
subset of
the Ruby/Rails community. We don’t have many sales reps who play golf
with
corporate executives.

The vast majority of those using Rails are fairly small companies trying
to
leverage the almost unique advantages of Ruby and Rails to be able to
quickly deploy into production, and incrementally improve core business
applications. And the vast majority of Rails developers are either
working
for those small companies, or for a small Rails consultancy, or as
independent freelance contractors.

they can keep using 1.8.6, which is maintained right now.

Very true, I’ve got no argument with that, but it’s important to
understand
that those who are using packaged distributions of Ruby from debian
(including Ubuntu), RedHat, macports etc. have more trouble keeping
1.8.6
because normal system administration has a nasty tendency to replace
1.8.6
with 1.8.x where x > 6 because they don’t differentiate versions with
differences in teeny version numbers as backwards incompatible. While
1.8.7
is backwards compatible with 1.8.6 in theory. Whether or not it really
is,
depends on whether or not all of the ancillary ruby code on the
particular
system, like Rails, Gems, and local applications have been kept, or
brought
up to date.

Savvy developers get around this by eschewing packaged versions and
installing the components of the Rails stack, including Ruby, from
source.
But there are a lot of developers who trust the package maintainers, and
run
into these issues, and end up blaming Ruby. We could say “well that’s
their
problem,” if we don’t care about the impact on the overall perception of
Ruby. Perhaps that’s the right attitude, but I’m not so sure.

Would it have been better for those with these problems had Ruby 1.8.7
not
included the changes from 1.9 which broke apps and frameworks? I think
that
the answer is clearly yes.

But, for better or worse, it did, and we have to live with the
consequences,
that doesn’t mean we need to be happy about it.

As EngineYard raised their hands, the maintenance of 1.8.6 will be

kept, even after 1.8.8.

If more evidence of great incompatibility is not shown, I will

consider it FUD, or FUD-like at most, even though I see no bad
intention from anyone.

I hope that this doesn’t come across as FUD, or even FUD-like, I’m just
trying to put a bit more context on why compatibility isn’t a black or
white
thing, and the sources of real FUD.

The real FUD doesn’t come from discussions like this, it comes from
those
who either have run into these problems and blame Ruby. We have no
control
over what they say, we can only try to consider the effects of decisions
on
the broader community, within the bounds of our human lack of complete
knowledge.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale

On Fri, Feb 13, 2009 at 10:14 AM, David A. Black [email protected]
wrote:

IMPLEMENT
Hash, and made this change in Ruby 1.9, which has been backported to Ruby
1.8.7.

Hashes aren’t ordered in 1.8.7, though.

Which makes this part of the thread rather moot, doesn’t it?!

Thanks for pointing that out.

Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale

On Fri, Feb 13, 2009 at 10:06 AM, M. Edward (Ed) Borasky
[email protected]wrote:

Someone suggested having 1.8.8 being 1.8.6 syntax and semantics with
only bug fixes, security fixes and efficiency enhancements. That appeals
to me … that way, “1.8.7” is a development release and “1.8.8” is
stable.

Bad idea, IMHO.

This would mean that Ruby 1.8.8, would be backwards compatible with
Ruby
1.8.6, but NOT with Ruby 1.8.7, which might be good for needing to say
with
the Ruby 1.8.6 definition, but not those who are already using Ruby
1.8.7.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale

Hi –

On Sat, 14 Feb 2009, James C. wrote:

I’m really not up for a slanging match so let me just say that, in code I’ve
written, Ruby < 1.8.7 has demonstrated the behaviour I described. This may
be a fluke or a bug, in which case I will investigate further and file bugs
if necessary.

It’s not a bug; there was never any defined order behavior, so no
behavior is either right or wrong.

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (The Well-Grounded Rubyist)

http://www.wishsight.com => Independent, social wishlist management!

+1 for the main question,
but…

On Feb 11, 9:15 pm, Charles Oliver N. [email protected]
wrote:

I still feel like Ruby 1.9 should have been 2.0.
Then 1.8.7 could have been 1.9, 1.8.8 could be 1.10,
and so on, …

I also agree about this. Perhaps it isn’t too late
to rename “1.9.1.0.0.1” to “2.0.0.0.1” ??

Also is it possible to make some “ruby20.rb” package
wich emulate some features of 1.9 present in 1.8.7?

Then in ruby-1.8.8 which would be 1.8.6 like
but would allow us to write:

require ‘ruby20’

Then all sugar features that are present in ruby 1.8.7
would be enable!
Perhaps this package could even be required from a 1.8.6
ruby version??

– Maurice

P.S.
+1 for the original question :wink:

On Fri, Feb 13, 2009 at 11:07 AM, David A. Black [email protected]
wrote:

if necessary.

I think it probably is machine-dependent, or something like that. I’ve
never heard of hash order being anything but “not guaranteed” before
1.9 – except that if you iterate twice, I believe it definitely
happens in the same order both times (though I’m not 100% sure that
that’s actually specified or guaranteed either).

No, it’s in the absence of key collisions, it’s really determined by the
hash values of the keys, The iteration is over the hash buckets and
hash
buckets marked as empty are skipped.

Consider your examples which I’ve excerpted:

% all-ruby -e ‘h = {2=>“b”, 1=>“a”}; p h’

ruby-1.8.6head(2009-02-13p330) {1=>“a”, 2=>“b”}

ruby-1.8.7head(2009-02-13p116) {1=>“a”, 2=>“b”}

ruby-1.9.1p0(2009-01-30r21907) {2=>“b”, 1=>“a”}

Note that for Ruby 1.8.6 and 1.8.7, the iteration order is by the sort
order
of the keys. But that’s just a side-effect of the hash of a fixnum
being
just the internal immediate representation which happens to be n*2 + 1
for a
Fixnum n:

irb(main):001:0> 1.hash
=> 3
irb(main):002:0> 2.hash
=> 5

Had you used what is arguably the more natural order in the literal,
i.e. {1
=> “a”, 2 => “b”} it would appear as if iteration was by insertion
order,
but that’s just an accidental artifact.

I suspect that those who observed that Ruby 1.8.7 ‘preserves’ insertion
order are looking at specific artificial cases like this.

Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale

demonstrate that it gives a **** about order of appearance
in a literal, or insertion order.

I’m really not up for a slanging match so let me just say that, in code
I’ve
written, Ruby < 1.8.7 has demonstrated the behaviour I described. This
may
be a fluke or a bug, in which case I will investigate further and file
bugs
if necessary. What I do know is that I’ve had code in a library released
over 2 years ago and used by a fair number of people relying on this
behaviour and heard no complaints until 1.8.7 arrived. I realise that
hashtables are not ordered in 1.8 and have since made my code more
robust.
I’m not questioning your examples – you can but experiment to see what
works – and I will try to extract the code from my project that
demonstrates my point when I have some time.

I’m not the least bit interested in who’s right or wrong or in berating
the
Ruby code devs or indeed anyone else, and was hoping for a productive
discussion, not people repeatedly asserting that I don’t know how a hash
table works and trying to shut me up. When I’ve time I’ll see if what I
have
is a Ruby bug or something else. Until then I’m canning this
conversation.

On Feb 13, 2009, at 9:06 AM, M. Edward (Ed) Borasky wrote:

BTW, Perl had no trouble going from 5.8.x to 5.10.x, and I understand
there is a 5.12.x coming. So I don’t see a problem with Ruby doing
similar things in the third digit. 1.8.10 works for me, as does
1.9.10. :slight_smile:

“1.8.9” < “1.8.10”
=> false

James Edward G. II

On Feb 13, 2009, at 3:53 AM, William J. wrote:

incompatibility.

No, it’s not a gray area. Anyone who has a basic understanding of
hash-tables doesn’t even think about the iteration order.

I guess you haven’t used Ruby 1.9. :slight_smile:

James Edward G. II

Hi –

On Sat, 14 Feb 2009, Rick DeNatale wrote:

supposed to now be defined behaviour I’ll investigate further and file a

ruby-1.8.7head(2009-02-13p116) {1=>“a”, 2=>“b”}
irb(main):002:0> 2.hash
=> 5

Had you used what is arguably the more natural order in the literal, i.e. {1
=> “a”, 2 => “b”} it would appear as if iteration was by insertion order,
but that’s just an accidental artifact.

That’s why I didn’t :slight_smile:

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (The Well-Grounded Rubyist)

http://www.wishsight.com => Independent, social wishlist management!

On Fri, Feb 13, 2009 at 8:11 AM, Rick DeNatale [email protected]
wrote:

I’m pretty sure that such “enterprisey” types make up a very small subset of
the Ruby/Rails community. We don’t have many sales reps who play golf with
corporate executives.

I saw a (fairly boring) panel discussion on “The Future of Enterprise
Software” by some of these “enterprisey” folks last night, including
the President of Oracle, who gave the keynote address. Yes, there is a
big difference between the 5-million ton gorilla Oracle (did you
know there are five million Oracle developers, all connected by Oracle
software?) and a typical Rails development team.

Very true, I’ve got no argument with that, but it’s important to understand
that those who are using packaged distributions of Ruby from debian
(including Ubuntu), RedHat, macports etc. have more trouble keeping 1.8.6
because normal system administration has a nasty tendency to replace 1.8.6
with 1.8.x where x > 6 because they don’t differentiate versions with
differences in teeny version numbers as backwards incompatible. While 1.8.7
is backwards compatible with 1.8.6 in theory. Whether or not it really is,
depends on whether or not all of the ancillary ruby code on the particular
system, like Rails, Gems, and local applications have been kept, or brought
up to date.

It’s not just the users … the packagers need to be in the loop
too. There are two main package formats – Debian/Ubuntu and RPM (Red
Hat / SuSE / Mandriva). And there are three major “community” Linux
distros as well as a few “Corporate” Linux entities. Sure, there are
differences in the details of how a Linux distro is packaged and
administered, but the tasks, issues and use cases are the same: first
of all it has to work, security holes need to be fixed ASAP,
preferably before exploits appear in the wild, and capacity planning
tools need to exist so that a supplier can be sure his service level
agreements are being met. The distinction here is not one of scale –
Oracle vs. a “typical Rails app”. The distinction is between a
production, deployed IT environment and a chaotic, risky experimental
venture.

I think we have to start thinking in terms of weeding out some of the
chaos. For example, I would expect openSUSE, Fedora and Ubuntu to be
all shipping a Ruby with identical syntax and semantics. I would
expect them all to be shipping a Rails with identical behavior. I
would expect to be able to walk up to a Ubuntu, openSUSE or Fedora
server console and type a distro install command to bring in any
Gem, not “sudo gem install ” because some gems are in
the package repository but others aren’t. In short, I would expect
that there would be one Ruby and one Rails, differing only in
whether I said “sudo apt-get install rails”, “sudo zypper install
rails”, or “sudo yum install rails”. It should just work.

This requires communication. This requires “marketing”. This requires
the kind of discussion we are having in this thread within the Ruby
community, but it also requires communication between the Ruby / Rails
communities and the distros. I haven’t done much in terms of syncing
up with the openSUSE community on Ruby, but I did get a sense of the
frustration with Ruby in the Gentoo community when I was a Gentoo
user.

M. Edward (Ed) Borasky

I’ve never met a happy clam. In fact, most of them were pretty steamed.