Hash of arrays - whats going on?

I want a hash, where the values of the keys are arrays, eg

h = Hash.new
h.default = []

h['foo'] << 10
h[foo'] << 20
h['bar'] << 23
h['bar'] << 33

I thought this would give me

{ 'foo' => [20 30],
  'bar' => [23, 33] }

but it doesn't - it seems to put the same array in the value of each
key. Some googling revealed I need to create my hash like:

h = Hash.new { |hash, key| hash[key] = [] }

So my problem is solved, but why do you have to do it like this? At
the risk of answering my own question, is it because the block is re-
executed everytime you access a non existent key, creating a brand new
array object, while the first way, it just initialises the value to
the same array each time?

Thanks,

Stephen.

default just lets you return a default value if the request key
doesn't exist, it's not _supposed_ to change the state of the hash.

What was happening is an array was presented to you when you called
h['foo'], and you were putting a value in it, but the array was never
saved to a variable, so it went away.

With the original code try the following code, it may help you understand:
h['foo'] << 10
puts h.length
h[foo'] << 20
puts h.length

The default value you provide is a reference... in this case, you say
"use this array as the default value", not "use an empty array as a
default value". To see what I mean, try this:

    empty_ary =
    h = Hash.new
    h.default = empty_ary

    h['foo'] << 10
    puts empty_ary.size

    h[foo'] << 20
    puts empty_ary.size

    h['bar'] << 23
    puts empty_ary.size

    h['bar'] << 33
    puts empty_ary.size

That should show you what's happening.

Ben

···

On Fri, Jul 20, 2007, stephen O'D wrote:

So my problem is solved, but why do you have to do it like this? At
the risk of answering my own question, is it because the block is re-
executed everytime you access a non existent key, creating a brand new
array object, while the first way, it just initialises the value to
the same array each time?