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] } }
Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!
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à!
Subscribe to RubyCademy and get free access to all our courses, plus hundreds of fun Ruby cards, quizzes, guides, and tutorials!
RubyCademy ©