On 9/1/06, Jia Pu <very.funny.j / gmail.com> wrote:
> Thanks, that works.
> I am wondering the requirement of #eql? is necessary. If the programmer
> wants to have non-equal objects to have same hash value, it is totally up to
> the programmer.
$ri Object#hash
------------------------------------------------------------ Object#hash
     obj.hash    => fixnum
------------------------------------------------------------------------
     Generates a +Fixnum+ hash value for this object. This function must
     have the property that +a.eql?(b)+ implies +a.hash == b.hash+. The
     hash value is used by class +Hash+. Any hash value that exceeds the
     capacity of a +Fixnum+ will be truncated before being used.

Note that the requirement is that if a.eql?(b) then a.hash must be == b.hash

This is because hash is used as a test to avoid a potentially
expensive .eql? test, if two object's DON'T have the same hash value
they are assumed to be not equal.

A Hash (I'm assuming here based on how hash algorithms work in
general) uses the hash of the key to compute an initial slot to store
a reference to an object when you put the object, at a particular key
in the hash with []=.  If that slot is empty that's where it goes.  If
it's not, meaning that there's a key there with the same hash, then it
uses eql? to see if it's the right slot, and if not it's called a hash
collision, and the hash calculates a new slot and repeats the process.
 Finding the object with a given key works basically the same way.

So the net of all this is, if you want hash to treat two different
instances  of your class as the same then you must redefine eql?, and
whenever you redefine .eql? then you need to redefine hash to make
sure that the implication in the specification of Object#hash holds.
-- 
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/