Strange behavior of hash key

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 ???

···

--
Traz

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

···

On Sat, 8 Jan 2005 15:56:26 +0900, Traz <A.Reith@gmail.com> wrote:

--
Matt Mower :: http://matt.blogs.it/

Matt Mower wrote:

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

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

···

On Sat, 8 Jan 2005 15:56:26 +0900, Traz <A.Reith@gmail.com> wrote:

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 ? :

"one".object_id

=> 22476232

"one".object_id

=> 22473868

This behavior is changing in 1.9:

Thank Joel ! So finaly, it was a bug in 1.8 ?

···

--
Traz

Hi 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 ? :
>> "one".object_id
=> 22476232
>> "one".object_id
=> 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.

>This behavior is changing in 1.9:
Thank Joel ! So finaly, it was a bug in 1.8 ?

Did they define Hash#eql? in 1.9?

Regards,

Matt

···

On Sat, 8 Jan 2005 17:51:25 +0900, Traz <A.Reith@gmail.com> wrote:

--
Matt Mower :: http://matt.blogs.it/

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 :wink:

M

···

On Sat, 8 Jan 2005 10:00:58 +0000, Matt Mower <matt.mower@gmail.com> wrote:

Hi Traz,

On Sat, 8 Jan 2005 17:51:25 +0900, Traz <A.Reith@gmail.com > wrote:
> >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 ? :
> >> "one".object_id
> => 22476232
> >> "one".object_id
> => 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.

--
Matt Mower :: http://matt.blogs.it/

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

···

In article <d563731905010802175d37f678@mail.gmail.com>, Matt Mower wrote:

On Sat, 8 Jan 2005 10:00:58 +0000, Matt Mower <matt.mower@gmail.com> wrote:

Hi Traz,

On Sat, 8 Jan 2005 17:51:25 +0900, Traz <A.Reith@gmail.com > wrote:
> >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 ? :
> >> "one".object_id
> => 22476232
> >> "one".object_id
> => 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.

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 :wink:

"Tim Sutherland" <timsuth@ihug.co.nz> schrieb im Newsbeitrag news:slrnctvdsn.hpb.timsuth@europa.zone...

Hi 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 ? :
> >> "one".object_id
> => 22476232
> >> "one".object_id
> => 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.

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 :wink:

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

···

In article <d563731905010802175d37f678@mail.gmail.com>, Matt Mower wrote:

On Sat, 8 Jan 2005 10:00:58 +0000, Matt Mower <matt.mower@gmail.com> >>wrote:

On Sat, 8 Jan 2005 17:51:25 +0900, Traz <A.Reith@gmail.com > wrote:

Hi Tim,

···

On Sat, 8 Jan 2005 19:36:26 +0900, Tim Sutherland <timsuth@ihug.co.nz> wrote:

>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 :wink:

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

--
Matt Mower :: http://matt.blogs.it/

This thread might be of interest:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/108521
-Charlie