0

console output:

2.1.3 :011 > b = Hash.new( Hash.new([]) )
 => {}
2.1.3 :012 > b[:a][:b] << 'hello'
 => ["hello"]
2.1.3 :013 > b
 => {}
2.1.3 :014 > b.size
 => 0
2.1.3 :015 > b.keys
 => []
2.1.3 :016 > b[:a][:b]
 => ["hello"]

Why is that I can access the value stored at b[:a][:b] yet b has a size of 0 and no keys?

Josh Diehl
  • 2,913
  • 2
  • 31
  • 43

1 Answers1

0

new(obj) → new_hash

If obj is specified, this single object will be used for all default values.

Now Hash.new([]) is holding the default Array object. Now b[:a][:b] << 'hello' you are entering, the "hello" to the default Array.The default value is being returned, when the key doesn't exist in the Hash.

Don't think you are adding keys to the Hash objects, with this b[:a][:b] << 'hello' line.

b[:a] is giving the default Hash object, which is Hash.new([]). Now on this Hash object you are calling Hash#[] using the key :b, but as :b is the non existent key, it is giving the default Array object.

That's why b, b.size and b.keys all are proving that Hash is empty.

Finally.

Why is that I can access the value stored at b[:a][:b] yet b has a size of 0 and no keys?

Because, you added the value "Hello" to the default Array, as I mentioned above. That value is coming when you are using the line b[:a][:b].

Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317
  • OK, I see what you mean, I created a single object the first time, which is being returned as the default always. Checked this with `b[:a][:c]` which also returned `["hello"]`. So, how do I accomplish the goal, which is to have a Hash of Hashes, where I can succinctly create two levels of keys and have a default array value at the same time? – Josh Diehl Oct 06 '14 at 19:24
  • @JoshDiehl Try this `new {|hash, key| block }` from the same link..Read documentation example. – Arup Rakshit Oct 06 '14 at 19:26
  • That syntax does work, this is what I'll use: `b = Hash.new {|h, k| h[k] = Hash.new {|h2, k2| h2[k2] = []}}`. Sure enough as you said it is right in the documentation, I just didn't think to look because it seems so counter-intuitive. I wonder if the case for wanting to use some single object as a default is more common than wanting to execute a new block. – Josh Diehl Oct 06 '14 at 19:40
  • @JoshDiehl That's why it is present there.. :-D – Arup Rakshit Oct 06 '14 at 19:42
  • @JoshDiehl The "default default" is `nil`, a single object. An often (most?) used "non-default default" is 0 (for counting things with `+= 1`), also a single object. – steenslag Oct 06 '14 at 21:56