LaunchKit
All quizzes
Ruby 1 views

A hash that contains itself under :b

Question

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

Explanation

TL;DR

hash[:b] = hash stores a reference to the hash inside itself, not a copy. Every [:b] lookup therefore returns the original hash, so hash[:b][:b][:b] is still hash, and the final [:a] reads the original pair: 1.

Step by step

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

hash[:b].equal?(hash)         # => true
hash[:b][:b].equal?(hash)     # => true
hash[:b][:b][:b].equal?(hash) # => true

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

Ruby variables and hash values hold references to objects. The assignment does not expand hash into a nested structure; it just makes the value under :b point back at the same object. Chaining [:b] any number of times, three or three thousand, lands on the same hash, and [:a] on that hash is 1.

Each [:b] is a single, ordinary hash lookup that returns immediately, so nothing recurses and no SystemStackError is possible here. The structure is cyclic; the access is not.

Edge cases

inspect has to deal with the cycle, and it does so with a placeholder instead of recursing forever:

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

hash.inspect # => "{a: 1, b: {...}}"

The {...} marks the point where the hash references itself. Operations that must fully traverse the structure are the dangerous ones: hash.to_a is fine (it is shallow), but recursively walking or deep-duplicating a self-referencing hash without cycle detection will loop or overflow the stack.

Share this quiz

Comments

No comments yet. Be the first.

Only used to confirm and publish your comment. Never shown publicly, never shared.

Markdown: **bold**, `code`, ```fenced blocks```, > quotes, [links](url). HTML and images are not rendered.