Hi --

On Sun, 4 Nov 2007, Jano Svitok wrote:

> On 11/3/07, Joshua Muheim <forum / josh.ch> wrote:
>> Hi all
>>
>> PHP lets me easily create multidimensional hashes using the following
>> syntax:
>>
>> x = array();
>> x["bla"]["some_key"] = true;
>>
>> Is Ruby not capable of doing this?
>>
>> x = []
>> x[:bla][:some_key] = true
>>
>> gives me a nil error!
>
> As David said, if you want to create hashes, you have to create Hashes ;-)
>
> Then, you can tell Hash.new what is the default value, so you can
> create hash, that will contain by default empty hashes:
>
> x = Hash.new { Hash.new }
>
> This will add an "automatic" two level hash. I don't know quickly how
> to make this indefinitly deep, you can at least repeat the pattern.
>
> Please note that it is not enough to write Hash.new { {} } as the
> inner will create one particular Hash instance, that all keys will
> reference. You need Hash.new to create a new hash for each key.

That's not quite right. The only-one-object thing is when you do this:

   h = Hash.new({})

If you use a block, it gets executed each time -- so in your example,
a new hash would get created.

However, it's important to remember that what you're setting is the
default value (or behavior) for *non-existent* keys. So if you do:

   h = Hash.new { {} }
   a = h[1]

a is now a hash, but h still has no keys.

The block is automatically passed the hash itself, and the key:

   h = Hash.new {|hash,key|  # do stuff with hash and key }

and you can use that fact to actually add the key to the hash.


David

-- 
Upcoming training by David A. Black/Ruby Power and Light, LLC:
   * Advancing With Rails, Edison, NJ, November 6-9
   * Advancing With Rails, Berlin, Germany, November 19-22
   * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
See http://www.rubypal.com for details!