Self-referential hashes

441 views

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

hash = {a: 1}
hash[:b] = hash

hash[:b][:b][:b][:a] # => ???

The correct answer is

nil

{a: 1, b: {...}}

1

SystemStackError

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

hash = {a: 1}
hash[:b] = hash

hash[:b][:b][:b][:a] # => 1

Explanation

  1. Initialization: We start by creating a hash with a single key-value pair:
hash = {a: 1}

At this point, the hash looks like this:

{a: 1}

  1. Self-Referencing Assignment: We then assign the :b key to point to the hash itself:
hash[:b] = hash

Now the hash references itself under the key :b, making it recursive:

{a: 1, b: {a: 1, b: {...}}}

The :b key holds a reference to the original hash, which includes itself.

  1. Chained Access: Finally, we access the :b key repeatedly:
hash[:b][:b][:b][:a]

Here’s how Ruby interprets this:

  • hash[:b] gives us the original hash.
  • hash[:b][:b] gives us the original hash again.
  • hash[:b][:b][:b] continues to return the original hash.

So, every time we access :b, we're just retrieving the original hash, which is {a: 1, b: {a: 1, b: {...}}}.

  1. Final Access: After resolving all the :b keys, we access the :a key of the final hash:
hash[:b][:b][:b][:a]

Since :a was originally set to 1, this entire chain of access ultimately returns:

hash[:b][:b][:b][:a] # => 1

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 ©