[Ruby] eql? and hash on Sets
Aaron Patterson
aaron at tenderlovemaking.com
Sat Nov 24 15:55:14 PST 2007
On Sat, Nov 24, 2007 at 02:22:49PM -0800, Scott Windsor wrote:
> A Set is intended to act like Array, but provide fast access for
> unordered values without duplicates. The documentation states that
> it uses a Hash for storage.
>
> You're incorrect that Set#eql? is implemented by Set. When you call
> Set#eql?, you're actually calling the inherited Object#eql? - which
> if you compare two different objects, they will not match. You can,
> however, use Set#== to determine if two sets are equal...
Interesting. This is from set.rb (around line 320):
def hash # :nodoc:
@hash.hash
end
def eql?(o) # :nodoc:
return false unless o.is_a?(Set)
@hash.eql?(o.instance_eval{@hash})
end
Do my eyes deceive me? I believe that Object#hash and Object#eql? are used
because (IIRC) hash does not implement eql? or .hash. However, it looks
like Set does in fact define those two methods.
[snip]
> Therefore, you'll always have to perform extra operations to
> determine Set equality. You can enhance this by sorting each Set
> first, then comparing, rather than comparing each without sorting,
> but this will still only get you to a worst case of nlogn rather than n.
Yes. My current implementation sorts the set by the hash of each
object, then does an eql? on the resulting array.
But my original question still remains. Since Set implements .eql? and .hash,
is this a bug? What was the original intent of this implementation?
--
Aaron Patterson
http://tenderlovemaking.com/
More information about the Ruby
mailing list