Search code examples
rubyhashautovivification

In ruby, why does array append fail on a hash with a default value of empty array?


Code example below. Calling append on a hash value returns correctly but the hash itself doesn't behave as I would expect.

ruby-1.9.2-p290 :037 >   r = {}
 => {} 
ruby-1.9.2-p290 :038 > r.default = []
 => [] 
ruby-1.9.2-p290 :039 > r["c"] << 1
 => [1] 
ruby-1.9.2-p290 :040 > r["c"] 
 => [1] 
ruby-1.9.2-p290 :041 > r
 => {} 
ruby-1.9.2-p290 :042 > r.empty?
 => true 

Solution

  • from the doc on default=:

    Sets the default value, the value returned for a key that does not exist in the hash. It is not possible to set the default to a Proc that will be executed on each key lookup.

    So you can use this:

    irb(main):037:0> h = Hash.new { |hash, key| hash[key] = [] }
    => {}
    irb(main):038:0> h[1] << "2"
    => ["2"]
    irb(main):039:0> h
    => {1=>["2"]}
    

    also you can use default_proc:

    irb(main):047:0> h = {}
    irb(main):047:0> h.default_proc =  proc {|hash, key| hash[key] = []}
    => #<Proc:0x23939a0@(irb):47> 
    irb(main):049:0> h[1] << 3
    => [3]
    irb(main):050:0> h
    => {1=>[3]}