Samuel Tesla wrote: > > Ferenc Engard <ferenc / engard.hu> writes: > > > What does hash comparison mean? I have read the Object#hash and > > Object#eql? documentation, but they do not mention arrays. Moreover, > > there comes the question: what the default Object#hash do? It has a > > generic algorithm which computes something based on the object's > > attributes? > > Hash comparison means that it compares the value of Object#hash for each > object. This is where a quick look at the Ruby source is very enlightening. > Having had to do some battle with these methods recently myself, I have the > code fresh in my mind. Object#hash just returns the object ID by default. > This is done in C code, so if you override Object#object_id, it will not return > what you expect. Sorry, I didn't look in the source, yet, but I have made some experiments with this simple program: class A attr_accessor :x def eql?(o) @x==o.x end def hash 15 end end a=A.new b=A.new c=A.new d=A.new a.x=1 b.x=2 c.x=2 d.x=3 ar1=[a,b] ar2=[b] ar3=[c] ar4=[d] ar5=[d,d] ar6=[b,c] puts "b.eql?(c)==true" puts "[a,b]=="+(ar1).inspect puts "[a,b].uniq=="+(ar1.uniq).inspect puts "[a,b]-[b]=="+(ar1-ar2).inspect puts "[a,b]-[c]=="+(ar1-ar3).inspect puts "[a,b]-[d]=="+(ar1-ar4).inspect puts "[d,d].uniq=="+(ar5.uniq).inspect puts "[b,c].uniq=="+(ar6.uniq).inspect ------------------------------------------------------------ The output is: b.eql?(c)==true [a,b]==[#<A:0x402d90ac @x=1>, #<A:0x402d8fe4 @x=2>] [a,b].uniq==[#<A:0x402d90ac @x=1>, #<A:0x402d8fe4 @x=2>] [a,b]-[b]==[#<A:0x402d90ac @x=1>] [a,b]-[c]==[#<A:0x402d90ac @x=1>] [a,b]-[d]==[#<A:0x402d90ac @x=1>, #<A:0x402d8fe4 @x=2>] [d,d].uniq==[#<A:0x402d8fbc @x=3>] [b,c].uniq==[#<A:0x402d8fe4 @x=2>] Which seems correct. Now if I comment out the hash method, the output changes: b.eql?(c)==true [a,b]==[#<A:0x402d9174 @x=1>, #<A:0x402d90d4 @x=2>] [a,b].uniq==[#<A:0x402d9174 @x=1>, #<A:0x402d90d4 @x=2>] [a,b]-[b]==[#<A:0x402d9174 @x=1>] [a,b]-[c]==[#<A:0x402d9174 @x=1>, #<A:0x402d90d4 @x=2>] [a,b]-[d]==[#<A:0x402d9174 @x=1>, #<A:0x402d90d4 @x=2>] [d,d].uniq==[#<A:0x402d90ac @x=3>] [b,c].uniq==[#<A:0x402d90d4 @x=2>, #<A:0x402d90c0 @x=2>] I.e. b and c are no longer considered equal. Based on that, I have made the following conclusion: 1. The array object first gets the hash of the objects it contains 2. If two object's hashes are not equal, then it considers as different objects 3. If the hash values are equal, then if first.eql?(second) is true, then it considers the objects as equal, otherwise not. Just like a hash index in a database. So, if I am lazy, can I implement the #hash method like this, and it will only result in a bigger comparison executing time because of the more #eql? comparisons, but will work correctly? Thanks for the help: Ferenc