[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Hash with two identical keys?

Trans

12/26/2006 5:48:00 PM

>From Facets' multiton.rb (which is primarily Floran Franks' work), I'm
getting somthing that doesn't make any sense:

POOLS[self] ||= {}
p POOLS[self].class
p POOLS[self].keys

Is outputing:

Hash
[[{:strip_comments=>false}], [{:strip_comments=>false}]]

How can two identical keys be in a hash?

T.


14 Answers

Alex LeDonne

12/26/2006 6:15:00 PM

0

On 12/26/06, Trans <transfire@gmail.com> wrote:
> >From Facets' multiton.rb (which is primarily Floran Franks' work), I'm
> getting somthing that doesn't make any sense:
>
> POOLS[self] ||= {}
> p POOLS[self].class
> p POOLS[self].keys
>
> Is outputing:
>
> Hash
> [[{:strip_comments=>false}], [{:strip_comments=>false}]]
>
> How can two identical keys be in a hash?
>
> T.
>
irb(main):005:0> bob = [{:whee => false}]
=> [{:whee=>false}]
irb(main):006:0> bob.hash
=> 23244868
irb(main):007:0> roger = [{:whee => false}]
=> [{:whee=>false}]
irb(main):008:0> roger.hash
=> 23235888
irb(main):009:0> bob.eql? roger
=> false
irb(main):010:0> bob[0].eql? roger[0]
=> false
irb(main):011:0> bob[0].hash
=> 23244870
irb(main):012:0> roger[0].hash
=> 23235890

I think it boils down to: there is no Hash#hash which inspects the
contents - Hash inherits Object#hash which is Object#object_id, and
the two hashes, while they appear to have the same contents, are not
the same object. So the keys are not "identical".

-A

Jon Garvin

12/26/2006 6:18:00 PM

0

Looks to me that your keys are arrays.

My guess is that

p POOLS[self].keys[0].class

will return Array, instead of Symbol, which is what you're probably
expecting. So, the hash doesn't have identical keys. It has two
different keys, each of which is a different array with identical
members. Try

p POOLS[self].keys[0].object_id
p POOLS[self].keys[1].object_id

and you'll see the keys really are different.

Trans wrote:
> >From Facets' multiton.rb (which is primarily Floran Franks' work), I'm
> getting somthing that doesn't make any sense:
>
> POOLS[self] ||= {}
> p POOLS[self].class
> p POOLS[self].keys
>
> Is outputing:
>
> Hash
> [[{:strip_comments=>false}], [{:strip_comments=>false}]]
>
> How can two identical keys be in a hash?
>
> T.
>
>
>
>


Trans

12/26/2006 7:06:00 PM

0

thanks Ara and Jon,

I see what your saying. I was using #== not #eql? in comparing the
keys. So I see why it's faling now. How do I get aorund this? I'm
caching object based on therr initialization paramaters, which has to
be an array. Is there a simpler way or do I have to do something like:

class Parameters < Array
alias :eql? :==
end

T.


Trans

12/26/2006 7:23:00 PM

0


Trans wrote:
> thanks Ara and Jon,
>
> I see what your saying. I was using #== not #eql? in comparing the
> keys. So I see why it's faling now. How do I get aorund this? I'm
> caching object based on therr initialization paramaters, which has to
> be an array. Is there a simpler way or do I have to do something like:
>
> class Parameters < Array
> alias :eql? :==
> end

Ugh. Nothing like that works either. It's not using eql? or equal?, but
rather #hash (I guess that's actually what you were trying to say Ara).
This doen't make any sense to me. Why do identical strings and arrays
have the same #hash value but not hashes?

T.


William James

12/26/2006 7:38:00 PM

0

Trans wrote:
> thanks Ara and Jon,
>
> I see what your saying. I was using #== not #eql? in comparing the
> keys. So I see why it's faling now. How do I get aorund this? I'm
> caching object based on therr initialization paramaters, which has to
> be an array. Is there a simpler way or do I have to do something like:
>
> class Parameters < Array
> alias :eql? :==
> end
>
> T.

How about association lists?

irb(main):029:0> a1=[[:strip,false]]
=> [[:strip, false]]
irb(main):030:0> a2=[[:strip,false]]
=> [[:strip, false]]
irb(main):031:0> h={}
=> {}
irb(main):032:0> h[a1] = 'foo'
=> "foo"
irb(main):033:0> h[a2] = 'bar'
=> "bar"
irb(main):034:0> h
=> {[[:strip, false]]=>"bar"}

Eric Hodel

12/26/2006 7:54:00 PM

0

On Dec 26, 2006, at 11:22, Trans wrote:
> Trans wrote:
>> thanks Ara and Jon,
>>
>> I see what your saying. I was using #== not #eql? in comparing the
>> keys. So I see why it's faling now. How do I get aorund this? I'm
>> caching object based on therr initialization paramaters, which has to
>> be an array. Is there a simpler way or do I have to do something
>> like:
>>
>> class Parameters < Array
>> alias :eql? :==
>> end
>
> Ugh. Nothing like that works either. It's not using eql? or equal?,
> but
> rather #hash (I guess that's actually what you were trying to say
> Ara).

A Hash only asks if one object is #eql? to another when they have the
same #hash. You can't use a Hash as a Hash key because Hash#hash is
not implemented that way.

> This doen't make any sense to me. Why do identical strings and arrays
> have the same #hash value but not hashes?

Likely because:

s = ''
s.hash

and:

a = []
a << a
a.hash

are easier to compute than:

h = {}
h[h] = h
h.hash

--
Eric Hodel - drbrain@segment7.net - http://blog.se...

I LIT YOUR GEM ON FIRE!


Trans

12/26/2006 7:57:00 PM

0


Trans wrote:
> Trans wrote:
> > thanks Ara and Jon,
> >
> > I see what your saying. I was using #== not #eql? in comparing the
> > keys. So I see why it's faling now. How do I get aorund this? I'm
> > caching object based on therr initialization paramaters, which has to
> > be an array. Is there a simpler way or do I have to do something like:
> >
> > class Parameters < Array
> > alias :eql? :==
> > end
>
> Ugh. Nothing like that works either. It's not using eql? or equal?, but
> rather #hash (I guess that's actually what you were trying to say Ara).
> This doen't make any sense to me. Why do identical strings and arrays
> have the same #hash value but not hashes?

Nope. It doesn't even use #hash. So it must be using #object_id with an
exception for Strings and Arrays. Dissapointing to say the least.

I had to resort to recursively converting all hashes to arrays.

T.


Trans

12/26/2006 8:10:00 PM

0


Eric Hodel wrote:
> On Dec 26, 2006, at 11:22, Trans wrote:
> > Trans wrote:
> >> thanks Ara and Jon,
> >>
> >> I see what your saying. I was using #== not #eql? in comparing the
> >> keys. So I see why it's faling now. How do I get aorund this? I'm
> >> caching object based on therr initialization paramaters, which has to
> >> be an array. Is there a simpler way or do I have to do something
> >> like:
> >>
> >> class Parameters < Array
> >> alias :eql? :==
> >> end
> >
> > Ugh. Nothing like that works either. It's not using eql? or equal?,
> > but
> > rather #hash (I guess that's actually what you were trying to say
> > Ara).
>
> A Hash only asks if one object is #eql? to another when they have the
> same #hash. You can't use a Hash as a Hash key because Hash#hash is
> not implemented that way.

I see. So it's not using object_id but

a.hash == b.hash && a.eql?(b)

Is that right?

> > This doen't make any sense to me. Why do identical strings and arrays
> > have the same #hash value but not hashes?
>
> Likely because:
>
> s = ''
> s.hash
>
> and:
>
> a = []
> a << a
> a.hash
>
> are easier to compute than:
>
> h = {}
> h[h] = h
> h.hash

Hmm... the expection gums up the works.

T.


Trans

12/26/2006 8:12:00 PM

0


William James wrote:
> Trans wrote:
> > thanks Ara and Jon,
> >
> > I see what your saying. I was using #== not #eql? in comparing the
> > keys. So I see why it's faling now. How do I get aorund this? I'm
> > caching object based on therr initialization paramaters, which has to
> > be an array. Is there a simpler way or do I have to do something like:
> >
> > class Parameters < Array
> > alias :eql? :==
> > end
> >
> > T.
>
> How about association lists?

Thanks William! That's what I did and worked (desipite inefficency).

T.


Trans

12/26/2006 8:15:00 PM

0


Trans wrote:
> thanks Ara and Jon,

Oops. Just saw that was Alex, not Ara, sorry about that Alex! And
thanks for the help.

T.