Hash & keys...

  • Thread starter Sébastien Wautelet
  • Start date
S

Sébastien Wautelet

I'm having some trouble understanding how hashes work in Ruby. Consider
the following test :

irb(main):002:0> v=Vector[4,5]
=> Vector[4, 5]
irb(main):003:0> v2=Vector[4,5]
=> Vector[4, 5]
irb(main):004:0> v==v2
=> true
irb(main):005:0> v.hash
=> 17
irb(main):006:0> v2.hash
=> 17
irb(main):007:0> h=Hash.new
=> {}
irb(main):008:0> h[v]="whatever is in (4,5)"
=> "whatever is in (4,5)"
irb(main):009:0> h[v2]
=> nil

I'd have expected h[v2] => "whatever is in (4,5)", since v==v2 and both
have the same hash value... what am I doing wrong?
 
T

Timothy Hunter

Sébastien Wautelet said:
I'm having some trouble understanding how hashes work in Ruby. Consider
the following test :

irb(main):002:0> v=Vector[4,5]
=> Vector[4, 5]
irb(main):003:0> v2=Vector[4,5]
=> Vector[4, 5]
irb(main):004:0> v==v2
=> true
irb(main):005:0> v.hash
=> 17
irb(main):006:0> v2.hash
=> 17
irb(main):007:0> h=Hash.new
=> {}
irb(main):008:0> h[v]="whatever is in (4,5)"
=> "whatever is in (4,5)"
irb(main):009:0> h[v2]
=> nil

I'd have expected h[v2] => "whatever is in (4,5)", since v==v2 and both
have the same hash value... what am I doing wrong?
It's not enough that they have the same hash value or that obj1 == obj2.
For the purposes of Hash, two objects are the same if obj1.eql?(obj2).
Does v1.eql?(v2)?
 
D

Daniel Waite

Sébastien Wautelet said:
I'd have expected h[v2] => "whatever is in (4,5)", since v==v2 and both
have the same hash value... what am I doing wrong?

Hash keys can be any object. So your hash, h, has one key, the object v.

Take another hash real quick, we'll call it hash.

hash = Hash.new

hash['rabbit'] = 'cute' # 'cute'
hash['blue'] # nil

The value for any hash key not defined is nil (unless you explicitly
tell the hash during instantiation to use another value).

So just because you're using the value of v as a key in your hash, does
not mean that v2 is automatically another key in your hash.
 
D

Daniel Waite

I think you're getting hung up on this part:

Sébastien Wautelet said:
irb(main):004:0> v==v2
=> true

Yes, v and v2 are equal. But that is irrelevant with regards to your
hash.

Now, if you had to objects that were identical (not equal, but
identical) then it would work:

s1 = 'string'
s2 = s1

h = Hash.new

h[s1] # 'string'
h[s2] # 'string'

s1.upcase!

h[s2] # 'STRING'
h[s1] # 'STRING'

Hope that helps.
 
K

Kenneth McDonald

Timothy said:
S=C3=A9bastien Wautelet said:
I'm having some trouble understanding how hashes work in Ruby.=20
Consider the following test :

irb(main):002:0> v=3DVector[4,5]
=3D> Vector[4, 5]
irb(main):003:0> v2=3DVector[4,5]
=3D> Vector[4, 5]
irb(main):004:0> v=3D=3Dv2
=3D> true
irb(main):005:0> v.hash
=3D> 17
irb(main):006:0> v2.hash
=3D> 17
irb(main):007:0> h=3DHash.new
=3D> {}
irb(main):008:0> h[v]=3D"whatever is in (4,5)"
=3D> "whatever is in (4,5)"
irb(main):009:0> h[v2]
=3D> nil

I'd have expected h[v2] =3D> "whatever is in (4,5)", since v=3D=3Dv2 a= nd=20
both have the same hash value... what am I doing wrong?

=20
It's not enough that they have the same hash value or that obj1 =3D=3D =
obj2. For the purposes of Hash, two objects are the same if=20
obj1.eql?(obj2). Does v1.eql?(v2)?
Testing reveals that they don't. but that strikes me as a bug in the=20
Vector class. It violates the guidelines given in the PickAxe book=20
(bottom of page 568), and more importantly, it violates common=20
intuition. If two vectors that are created in exactly the same manner=20
aren't eql?, they're useless for use as hash keys. I'd say file a bug=20
report, or at least a problem, on this one.

Cheers,
Ken
 
P

Phrogz

Daniel said:
I think you're getting hung up on this part:



Yes, v and v2 are equal. But that is irrelevant with regards to your
hash.

Now, if you had to objects that were identical (not equal, but
identical) then it would work:

I think it is relevant, given that the Vector class is designed to be
immutable. I would agree that the Vector class should probably define
#eql? as an alias for #==.
 
R

Rick DeNatale

I think it is relevant, given that the Vector class is designed to be
immutable. I would agree that the Vector class should probably define
#eql? as an alias for #==.

It appears to be a typo in Matrix.rb - This is in ruby1.8.4:

class Vector
...
#
# Returns +true+ iff the two vectors have the same elements in the same order.
#
def ==(other)
return false unless Vector === other

other.compare_by(@elements)
end
alias eqn? ==
~~~

And Vector seems to be the only implementor of eqn?

rick@frodo:~/ruby-1.8.4$ ri eqn
------------------------------------------------------------ Vector#eqn?
eqn?(other)
------------------------------------------------------------------------
Alias for #==

And it's not yet fixed in 1.9
rick@frodo:~/ruby-1.8.4$ grep eqn /public/rubysource/ruby1.9/ruby/lib/matrix.rb
alias eqn? ==
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Ruby Hash Keys and Related Questions 6
Class instance method 2
Hash behavior query 2
Ruby hash equlity 4
what does print call internally? 12
Hash keys don't work as expected 10
Socket hang in thread 1
IO.pos bug? 5

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top