Can someone explain this syntax in new?

I found this in an old post:

"Here’s a Hash that automatically creates new hashes for each key you
try to access (specifically 1-level deep for a ‘2-dimensional’ hash):

people = Hash.new{ |me,key| me[ key ] = {} }
people[ :gavin ][ :age ] = 34
people[ :gavin ][ :sex ] = :male
people[ :fido ][ :species ] = :dog
p people
#=> {:gavin=>{:age=>34, :sex=>:male}, :fido=>{:species=>:dog}}

…but there was no further explanation. Could somebody explain the
syntax in the first line? Is this overwriting new()?

Thanks,
Robb

Robb Shecter wrote:

people = Hash.new{ |me,key| me[ key ] = {} }
[…]
 Is this overwriting new()?

No, it calls new and passes the above block to it.
The block will then be stored and executed every time a key is accessed
that
does not exist (with the hash object and the requested key as
arguments).

HTH,
Sebastian

On Tuesday 27 May 2008, Robb Shecter wrote:

p people
#=> {:gavin=>{:age=>34, :sex=>:male}, :fido=>{:species=>:dog}}

…but there was no further explanation. Could somebody explain the
syntax in the first line? Is this overwriting new()?

Thanks,
Robb

If you look at the ri documentation for Hash#new, you’ll see that it can
be
used in three form: the first is Hash.new() which returns an hash with a
default value of nil; the second is Hash.new(obj) which returns an hash
with a
default value of obj. This means that whenever you try to access an
element
using a key which is not in the hash, the method will return obj. The
third
form of new takes a block. Whenever you try to access a nonexistent key,
the
block is called with two arguments: the hash itself and the key. In the
block
you can do whatever you want, including computing a value from the key
and
storing it in the hash.

In the code you posted, the block simply stores a new, empty hash under
the
key key of the hash.

I hope this helps

Stefano

Sebastian H. wrote:

No, it calls new and passes the above block to it.
The block will then be stored and executed every time a key is accessed
that
does not exist (with the hash object and the requested key as
arguments).

Ah hah. I see; this is a particular feature of the Hash class – one of
the three ways to invoke new(). Thanks!

try to access (specifically 1-level deep for a ‘2-dimensional’ hash):
…but there was no further explanation. Could somebody explain the
syntax in the first line? Is this overwriting new()?

No, this is calling new() with a block. In this case, for keys that are
not yet in the hash, the specified block will be called with 2
parameters: one is the hash object itself, and the second one a key
being accessed. This gives you an opportunity to initialize a value at
that key appropriately (in the example before, it is initialized to
another hash - {} is a literal for a hash, equivalent to Hash.new).

Gennady.