Hash.new { [] }

738 views

What's the return value of the following Ruby code?

h = Hash.new { [] }

h[:a] << 42
h[:b] << 84

h # => ???

The correct answer is

{}

{ a: 42, b: 84 }

{ b: 84 }

{ a: { b: [42, 84] } }

Unlock Your Ruby Potential

Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!

Explanation

This Ruby code initializes a hash h with a default value defined by a block.

However, the block is returning an empty array [] instead of using the typical Hash.new {|h,k| h[k] = []} approach to create a new empty array when a key doesn't exist.

When you try to append values to h[:a] and h[:b], the code will execute h[:a] << 42 and h[:b] << 84.

However, since the default value is an empty array [], instead of inserting elements into h[:a], it's trying to append elements directly to an empty array.

h[:a].object_id # => 44660
h[:a].object_id # => 48000

So every time you call Array#<< on h[:a] or h[:b] a new default array (with a different object ID) is returned and Array#<< is called on it.

But as it's a default value that is called when the key doesn't exist in h, the key is obviously not created and the new array is not inserted as the value of the given key.

This results in h remaining an empty hash {} because no new key-value pair is being created.

So, despite the attempts to append elements to h[:a] and h[:b], the hash remains unchanged, resulting in an empty hash being returned when accessing h.

Voilà!

Unlock Your Ruby Potential

Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!

RubyCademy ©