Strange behavior of hash key

T

Traz

Hello all,
I want to use some hash who have a hash key. But, i don't understand
the hash key behaviour :
a={} => {}
a[{1,2}]='ok' => "ok"
a[{1,2}] => nil
a.keys => [{1=>2}]
a.keys[0] == {1,2} => true
a.keys[0].eql?({1,2}) => false
a[a.keys[0]]
=> "ok"
So, why i can't access to the hash with a hash key ???
 
M

Matt Mower

Hi Traz,

Hello all,
I want to use some hash who have a hash key. But, i don't understand
the hash key behaviour :
a={} => {}
a[{1,2}]='ok' => "ok"
a[{1,2}]
=> nil

I believe the answer is because each time you use {1,2} you are
creating a new Hash object with the same contents but a different
object identity:

irb(main):017:0> {1,2}.object_id
=> 22400644
irb(main):018:0> {1,2}.object_id
=> 22396300

Because Hash uses Object#eql? to test for equality it makes them
different keys and hence your example fails.

Hope this helps,

Matt
 
J

Joel VanderWerf

Matt said:
Hi Traz,

Hello all,
I want to use some hash who have a hash key. But, i don't understand
the hash key behaviour :


=> {}
a[{1,2}]='ok'

=> "ok"

=> nil


I believe the answer is because each time you use {1,2} you are
creating a new Hash object with the same contents but a different
object identity:

irb(main):017:0> {1,2}.object_id
=> 22400644
irb(main):018:0> {1,2}.object_id
=> 22396300

Because Hash uses Object#eql? to test for equality it makes them
different keys and hence your example fails.

Hope this helps,

Matt

This behavior is changing in 1.9:

$ ruby -v -e 'a={ {1,2}=>3 }; p a[{1,2}]'
ruby 1.8.2 (2004-12-25) [i686-linux]
nil
$ ruby-snapshot -v -e 'a={ {1,2}=>3 }; p a[{1,2}]'
ruby 1.9.0 (2004-12-26) [i686-linux]
3
 
T

Traz

Because Hash uses Object#eql? to test for equality it makes them
different keys and hence your example fails.

Matt, string keys have the same behaviour, no ? :=> 22473868
This behavior is changing in 1.9:
Thank Joel ! So finaly, it was a bug in 1.8 ?
 
M

Matt Mower

Hi Traz,

Matt, string keys have the same behaviour, no ? :
=> 22473868

I think the answer here is that String redefines the eql? method to
compare content instead of 'object_id' so String literal keys will
work.
Thank Joel ! So finaly, it was a bug in 1.8 ?

Did they define Hash#eql? in 1.9?

Regards,

Matt
 
M

Matt Mower

Hi Traz,



I think the answer here is that String redefines the eql? method to
compare content instead of 'object_id' so String literal keys will
work.

Hmm... except that I tried a naive redefinition of Hash#eql? to:

def eql?( o ); self == o; end;

and the example still doesn't work. Guess I'm just wrong ;-)

M
 
T

Tim Sutherland

Hmm... except that I tried a naive redefinition of Hash#eql? to:

def eql?( o ); self == o; end;

and the example still doesn't work. Guess I'm just wrong ;-)

You also need to define Hash#hash so that eql objects have the same hash
code.
 
R

Robert Klemme

Tim Sutherland said:
You also need to define Hash#hash so that eql objects have the same hash
code.

Note also that equivalence of Hashes is not a simple concept: in some
situations you want to include the default value and / or block into
equivalence and sometimes you don't. I guess that's the reason why this was
left open for quite some time. The most pragmatic solution is to define
hashes with the same key value pairs, the same default value and without a
block to be equivalent and all others to not be equivalent.

Kind regards

robert
 
M

Matt Mower

Hi Tim,

You also need to define Hash#hash so that eql objects have the same hash
code.

Of course, I got sidetracked by eql? and forgot that the problem was,
ultimately, about the hashing function. The real answer was in the
difference between Object#hash which presumably uses object_id and
String#hash which uses length & content.

Thanks for putting me straight,

Matt
 

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

Members online

No members online now.

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top