On Mar 28, Robert Klemme wrote:
> I think in older versions you can achieve this by
> (h["a"] ||= [])[0] = "something"
> 
> I think newer versions can do
> 
> h = Hash.new{Array.new}
> h["a"][0] = "something"
> 
> Regards
> 
>     robert
> 
> 

The first works:
vor-lord:i686/debug> irb
irb(main):001:0> h = Hash.new
=> {}
irb(main):002:0> (h["a"] ||= [])[0] = "something"
=> "something"
irb(main):003:0> h["a"]
=> ["something"]
irb(main):004:0> h["a"][0]
=> "something"

I'm not sure this is as clear as I'd like, I'd probably choose to do something
easier to read but more verbose:

h["a"] = Array.new unless h.include?("a")
h["a"][0] = "something"


But your second example doesn't work with CVS Ruby from two days ago:

vor-lord:i686/debug> irb
irb(main):001:0> RUBY_VERSION
=> "1.8.0"
irb(main):002:0> h = Hash.new{Array.new}
=> {}
irb(main):003:0> h["a"][0] = "something"
=> "something"
irb(main):004:0> h["a"]
=> []
irb(main):005:0> h["a"][0]
=> nil

I understand Hash.new(Array.new) even though I was caught trying to do the
following once (ok, twice ;) upon a time:

irb(main):001:0> h = Hash.new(Array.new)
=> {}
irb(main):002:0> h["a"][0] = "something"
=> "something"
irb(main):003:0>  h["a"]
=> ["something"]
irb(main):004:0> h["a"][0]
=> "something"
irb(main):005:0> h["b"][0] = "something_else"
=> "something_else"
irb(main):006:0> h["a"]
=> ["something_else"]

OOPS!  The same object is returned as the default value.

It looks like the block form gives you a new object each time to return when a
key doesn't exist in the hash, but it doesn't assign that as the value of the
key.  Is that correct?:

irb(main):001:0> h = Hash.new{Array.new}
=> {}
irb(main):002:0> h["a"][0] = "something"
=> "something"
irb(main):003:0> h.keys
=> []

{Array.new} gives:
irb(main):001:0> h = Hash.new{Array.new}
=> {}
irb(main):002:0> h["foo"].id
=> 537955172
irb(main):003:0> h["bar"].id
=> 537950392
irb(main):004:0> h["foo"].id
=> 537945462


whereas (Array.new) gives:
irb(main):001:0> h = Hash.new(Array.new)
=> {}
irb(main):002:0> h["foo"].id
=> 537959972
irb(main):003:0> h["bar"].id
=> 537959972

So the block form gives you a unique object for each call to a non-existent
key, but still doesn't implicitly assign anything to that key.  So in your
second example the Array.new is created and has [0] assigned, but there are no
references to it so it will just be garbage collected.

Thanks for the tip though, I wasn't aware of the block form, that is a cool new
feature that I can make use of!