On Tuesday 05 January 2010 09:39:53 pm Ruby Newbee wrote:
> irb(main):039:0> hash = Hash.new []

I assume here that [] is the default value, right?
> => {}
> irb(main):040:0> hash['abc'] << 3
> => [3]
> irb(main):041:0> hash.keys
> => []
> irb(main):042:0> hash['def']
> => [3]
> 
> 
> Since I have created a key/value pair with hash['abc'] << 3, why
> hash.keys show nothing?

Because you haven't set anything in the hash. That is,

hash['abc'] = 3

is equivalent to:

hash.[]=('abc', 3)

On the other hand, what you've done is:

hash['abc'] << 3

That's equivalent to:

hash.[]('abc') << 3

I don't know if that helps, but that's the difference. Let me put it this way 
-- suppose you hadn't changed the default value:

irb(main):001:0> hash = {}
=> {}
irb(main):002:0> hash['abc']
=> nil
irb(main):003:0> hash.keys
=> []

Do you understand why that works the way it does? But there's nothing special 
about nil here, it's just the, erm, _default_ default value -- it's what Hash 
uses as a default value if you don't specify one.

> And, why hash['abc'] << 3 changed the hash's default value (which
> should be an empty array)?

Because you set the default value to [], which creates an empty array object, 
once. The hash is just assigning it each time. Think of it this way:

irb(main):004:0> default = []
=> []
irb(main):005:0> a = default
=> []
irb(main):006:0> b = default
=> []
irb(main):007:0> a << 3
=> [3]
irb(main):008:0> b
=> [3]

What you really want is the block notation of creating a hash, which lets you 
actually specify some code that's run to create a default value, as Bill Kelly 
says. The reason his code works is that when you try to access a value that 
doesn't exist, it actually runs some code which sets that value:

h = Hash.new {|h,k| h[k] = []}

It wouldn't work at all if you just did this:

h = Hash.new {|h,k| []}

That would at least give you a new array each time, but since it wouldn't set 
it, you'd see weird things:

irb(main):010:0> h['abc'] << 3
=> [3]
irb(main):011:0> h['abc']
=> []
irb(main):012:0> h.keys
=> []