[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Hash hidden in hash with default object

Marcel Molina Jr.

6/25/2005 3:54:00 PM

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>


3 Answers

Marcel Molina Jr.

6/25/2005 4:26:00 PM

0

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

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


Austin Ziegler

6/25/2005 4:28:00 PM

0

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

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


Marcel Molina Jr.

6/25/2005 4:34:00 PM

0

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

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