Hash hidden in hash with default object

M

Marcel Molina Jr.

I observed this odd behavior when setting a hash to have as its default
value another hash which itself has a default value set:
hash_in_hash = Hash.new(Hash.new([])) => {}
hash_in_hash[:a][:b] << :incognito => [:incognito]
hash_in_hash => {}
hash_in_hash[:a] => {}
hash_in_hash.keys => []
hash_in_hash[:a][:b] => [:incognito]
hash_in_hash[:a].keys
=> []

?

marcel
 
M

Marcel Molina Jr.

I observed this odd behavior when setting a hash to have as its default
value another hash which itself has a default value set:
hash_in_hash = Hash.new(Hash.new([])) => {}
hash_in_hash[:a][:b] << :incognito => [:incognito]
hash_in_hash => {}
hash_in_hash[:a] => {}
hash_in_hash.keys => []
hash_in_hash[:a][:b] => [:incognito]
hash_in_hash[:a].keys
=> []

Responding to myself...

To achieve the desired result in this case I should be using the block form.

Thanks for taking a look. I'll figure this out...

marcel
 
A

Austin Ziegler

I observed this odd behavior when setting a hash to have as its default
value another hash which itself has a default value set:
hash_in_hash =3D Hash.new(Hash.new([])) =3D> {}
hash_in_hash[:a][:b] << :incognito =3D> [:incognito]
hash_in_hash =3D> {}
hash_in_hash[:a] =3D> {}
hash_in_hash.keys =3D> []
hash_in_hash[:a][:b] =3D> [:incognito]
hash_in_hash[:a].keys
=3D> []

That's now how you want to do this in any case, because that doesn't
actually *set* the key. Even if it did, it's still probably not what
you want, because all of the secondary hashes will be referencing
the same array as their default value, e.g.:

hash_in_hash[:a][:c] << :cognito
=3D> [:incognito, :cognito]

Instead, do:

hash_in_hash =3D Hash.new { |h, k|
h[k] =3D Hash.new { |h1, k1|
h1[k1] =3D []
}
}

-austin
--=20
Austin Ziegler * (e-mail address removed)
* Alternate: (e-mail address removed)
 
M

Marcel Molina Jr.

I observed this odd behavior when setting a hash to have as its default
value another hash which itself has a default value set:
hash_in_hash = Hash.new(Hash.new([])) => {}
hash_in_hash[:a][:b] << :incognito => [:incognito]
hash_in_hash => {}
hash_in_hash[:a] => {}
hash_in_hash.keys => []
hash_in_hash[:a][:b] => [:incognito]
hash_in_hash[:a].keys
=> []

That's now how you want to do this in any case, because that doesn't
actually *set* the key. Even if it did, it's still probably not what
you want, because all of the secondary hashes will be referencing
the same array as their default value, e.g.:

hash_in_hash[:a][:c] << :cognito
=> [:incognito, :cognito]

Instead, do:

hash_in_hash = Hash.new { |h, k|
h[k] = Hash.new { |h1, k1|
h1[k1] = []
}
}

Thanks for the reply. That's exactly what I came up with except I foolishly
did

Hash.new {|h,k| h[k] = Hash.new {|h1,k1| h1[k1] ||= [] }}

(difference is ||= [] vs = []) which causes SystemStackError.

Thanks again.

marcel
 

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

Staff online

Members online

Forum statistics

Threads
474,175
Messages
2,570,942
Members
47,489
Latest member
BrigidaD91

Latest Threads

Top