Hash hidden in hash with default object

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

···

--
Marcel Molina Jr. <marcel@vernix.org>

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

···

On Sun, Jun 26, 2005 at 12:53:59AM +0900, Marcel Molina Jr. wrote:

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 Molina Jr. <marcel@vernix.org>

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] =
    }
  }

-austin

···

On 6/25/05, Marcel Molina Jr. <marcel@vernix.org> wrote:

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

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

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

···

On Sun, Jun 26, 2005 at 01:28:08AM +0900, Austin Ziegler wrote:

On 6/25/05, Marcel Molina Jr. <marcel@vernix.org> wrote:
> 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] =
    }
  }

--
Marcel Molina Jr. <marcel@vernix.org>