When I initialize a Ruby hash with a default value like 0 and create a new entry in the hash and increment it behaves as expected:
irb(main):001:0> h1 = Hash.new(0)
=> {}
irb(main):002:0> h1[:foo] += 1
=> 1
irb(main):003:0> h1
=> {:foo=>1}
irb(main):004:0> h1[:foo]
=> 1
Notice how h1 #=> {:foo=>1}
and h1[:foo] #=> 1
. That's what I was expecting to see.
Except if I use a default value of an empty array then this is what happens:
irb(main):005:0> h2 = Hash.new([])
=> {}
irb(main):006:0> h2[:foo] << "cats"
=> ["cats"]
irb(main):007:0> h2
=> {}
irb(main):008:0> h2[:foo]
=> ["cats"]
Notice how h2 #=> {}
and h2[:foo] #=> ["cats"]
. I don't know why this is happening.
- What is going on here?
- Why does h2 look like an empty hash but then still has a value with the key
:foo
?
If I use some a block then the expected behavior happens:
irb(main):001:0> h3 = Hash.new {|hash, key| hash[key] = [] }
=> {}
irb(main):002:0> h3[:foo] << "cats"
=> ["cats"]
irb(main):003:0> h3
=> {:foo=>["cats"]}
irb(main):004:0> h3[:foo]
=> ["cats"]
Notice how h2 #=> {:foo=>["cats"]}
and h3[:foo] #=> ["cats"]
. That's what I was expecting to see.