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