Hash freezes String keys are returns copy

M

Michael Neumann

Hi,

My observation is, that Hash behaves differently for different kinds of
objects. While an Object key is preserved as is, a String key isn't
(it's frozen and a copy is returned)! I'd like to get back my original
key from a Hash, but with String keys this is not possible.

a = 'test'
b = Object.new

h = {}
h[a] = a
h = b

h.each do |k,v|
puts "key: "
p k
p k.object_id
p k.frozen?

puts "value: "
p v
p v.object_id
p v.frozen?
end

The result is (indented for readability):

key:
#<Object:0x81f239c>
68129230
false
value:
#<Object:0x81f239c>
68129230
false

key:
"test"
68135310
true
value:
"test"
68135320
false


Is this intended behaviour?

So in my case, instead of { obj => data }, I now have to store
{ obj => [obj, data] }, as I can't get the original object "obj" back.

Regards,

Michael
 
T

ts

M> Is this intended behaviour?

What do you do in this case ?

a = "test"
hash[a] = "test"
a[0] = "m"
p hash.keys



Guy Decoux
 
M

Michael Neumann

ts said:
M> Is this intended behaviour?

What do you do in this case ?

a = "test"
hash[a] = "test"
a[0] = "m"
p hash.keys

But why does this work:

a = []
hash[a] = "test"
a[0] = "1"
p hash.keys
# => returns [ ["1"] ]

Regards,

Michael
 
T

ts

M> But why does this work:

M> a = []
M> hash[a] = "test"
M> a[0] = "1"
M> p hash.keys
M> # => returns [ ["1"] ]

uln% cat b.rb
#!/usr/local/bin/ruby
a = []
hash = { a => "test"}
a[0] = "1"
p hash[a]
uln%

uln% b.rb
nil
uln%


Guy Decoux
 
M

Michael Neumann

ts said:
M> But why does this work:

M> a = []
M> hash[a] = "test"
M> a[0] = "1"
M> p hash.keys
M> # => returns [ ["1"] ]

uln% cat b.rb
#!/usr/local/bin/ruby
a = []
hash = { a => "test"}
a[0] = "1"
p hash[a]
uln%

uln% b.rb
nil
uln%

okay... but isn't it the same when using a String?

a = ""
hash = { a => "test" }
a << "1"
p hash[a] # => nil
p hash.keys # => [""]

while:

a = []
hash = { a => "test" }
a << "1"
p hash[a] # => nil
p hash.keys # => [["1"]]

they behave differently.

Regards,

Michael
 
T

ts

M> okay... but isn't it the same when using a String?

this is made volontary for efficienty : otherwise each time that you
modify an object, used as a key, ruby will need to re-hash the hash if you
don't want to have strange result like the example that I've given

In reality when you write

a = "test"
hash[a] = "test"

the key and `a' share the same string, but `a' is marked copy-on-write

M> they behave differently.

Search the archive of [ruby-talk] for this :)


Guy Decoux
 
M

Michael Neumann

ts said:
M> okay... but isn't it the same when using a String?

this is made volontary for efficienty : otherwise each time that you
modify an object, used as a key, ruby will need to re-hash the hash if you
don't want to have strange result like the example that I've given

In reality when you write

a = "test"
hash[a] = "test"

the key and `a' share the same string, but `a' is marked copy-on-write

M> they behave differently.

Search the archive of [ruby-talk] for this :)

Ah, IIRC it has something to do with common usage of strings as keys.


Regards,

Michael
 
R

Robert Klemme

Michael Neumann said:
ts said:
"M" == Michael Neumann <[email protected]> writes:


M> okay... but isn't it the same when using a String?

this is made volontary for efficienty : otherwise each time that you
modify an object, used as a key, ruby will need to re-hash the hash if
you
don't want to have strange result like the example that I've given

In reality when you write

a = "test"
hash[a] = "test"

the key and `a' share the same string, but `a' is marked copy-on-write

M> they behave differently.

Search the archive of [ruby-talk] for this :)

Ah, IIRC it has something to do with common usage of strings as keys.

Yes, it's a special optimization for string keys. You can get your original
out if you freeze it before putting it into the hash. :) In fact, that
might be a performance optimization if you put *a lot* string keys into the
hash.

Because copying an instance is relatively expensive this pattern was not
adopted generally, i.e. you have to take care of Array and other keys
yourself. Note also, that you need to rehash if you change your array
instance after using it as Hash key.

Kind regards

robert
 

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

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top