From: Christoph Date: 2004-03-02T03:34:45+09:00 Subject: Re: Set of Sets and eql? Tim Sutherland wrote: .... > I just realised why :) > > It's because we require that a.eql?(b) implies a.hash == b.hash. > > Forcing people who define #== to be structural equality to also define #hash > to follow this would be an onerous restriction. > > Similarly, defining Set#hash that behaves nicely if eql? is == is tricky > because we don't have a nice ordering of elements in the set. Need something > like SortedSet but with sort_by to use ==. (Since element#<=> does not have > to match element#==.) > You don't need an ordering to define a nice Set#eql? (resp. Set#hash) method. Essentially something like class Set def eql?(rhs) rhsh = @rhs.hash return false unless @hash.size == rhsh.size @hash.each_key {|e| return false unless rhs.has_key?(e)} return true end def hash # some silly order independent hash ... hsh = @hash.size + 1743 _hsh = hsh*hsh @hash.each_key {|e| ehsh = e.hash hsh += ehsh _hsh ^= (ehsh >> 13) } return (hsh && _hsh) + hsh end end would do. The Set class author was certainly aware of this possibility but (probably) decided against it since he modeled his Set class more closely around Ruby's Hash class than classical mathematical sets. The current Set#<=> implementation is IMO even more debatable since it is based on the sets size rather than their actual members (this is akin to the dubious Complex#<=> definition which which still ticks me off after > 3 years). /Christoph