From: Rick DeNatale Date: 2010-12-02T09:11:03+09:00 Subject: Re: hash method how-to? On Wed, Dec 1, 2010 at 2:27 PM, Yossef Mendelssohn wrote: > On Dec 1, 1:10 pm, niklas | brueckenschlaeger > wrote: >> http://en.wikipedia.org/wiki/Hash_function >> >> in most cases it's the easiest to delegate the hash method to something >> else. Example: >> >> class X >>   def initialize(name) >>     @name = name >>   end >> >>   def hash >>     @name.hash >>   end >> end >> >> h = { X.new("foo") => "bar" } >> h[X.new("foo")] = "baz" # will overwrite the above > > And so will `h['foo'] = 'baz'`. No neither will: class X attr_reader :name def initialize(name) @name = name end def hash @name.hash end def inspect "X:#{@name.inspect}" end end h = { X.new("foo") => :bar} h[X.new("foo")] = :baz h["foo"] = :bat h # => {"foo"=>:bat, X:"foo"=>:baz, X:"foo"=>:bar} The reason is that the value of #hash is not the only thing needed to distinguish hash keys. All objects with the same hash value are mapped to the same hash 'bucket' hash collisions are resolved by using the eql? method, X.new("a").eql?(X.new("a")) # => false class X def eql?(other) other.class == X && # One of the rare occurrences when checking the class is a good thing name.eql?(other.name) end end h = { X.new("foo") => :bar} h[X.new("foo")] = :baz h["foo"] = :bat h # => {"foo"=>:bat, X:"foo"=>:baz} X.new("a").eql?(X.new("a")) # => true Note that the Hash class depends on a relationship between eql? and hash, that a.eql?(b) => a.hash == b.hash where => here is logical implication, that is a => b is the same as b ||| !a -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Github: http://github.com/rubyredrick Twitter: @RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale