这个红宝石片段如何工作?

nas*_*der 4 ruby hash

难题:

something = {}
another = something
('a'...'f').each do |x|
  puts "another = #{another} and x= #{x} and something = #{something}"
  another = (another[x] ||= {})
end
puts something
Run Code Online (Sandbox Code Playgroud)

输出:

=>another = {} and x= a and something = {}
=>another = {} and x= b and something = {"a"=>{}}
=>another = {} and x= c and something = {"a"=>{"b"=>{}}}
=>another = {} and x= d and something = {"a"=>{"b"=>{"c"=>{}}}}
=>another = {} and x= e and something = {"a"=>{"b"=>{"c"=>{"d"=>{}}}}}
Run Code Online (Sandbox Code Playgroud)

现在乍一看它看起来像'另一个'和'某事'都指向相同的哈希对象,但如果是这种情况,那么在输出'另一个'将匹配'某事'.那么变量'something'如何不是空哈希?

Max*_*Max 6

在Ruby中,一切都是一个对象,所有对象都是使用指针传递的(有例外,但这里不适用).当你这样做

something = {}
another = something
Run Code Online (Sandbox Code Playgroud)

创建单个Hash对象,并且两个变量都指向同一个对象.当你这样做

another[x] ||= {}
Run Code Online (Sandbox Code Playgroud)

创建一个Hash对象,并将指向该对象的指针添加到指向的Hash another.另一种写作方式是

old_hash = another
new_hash = {}
old_hash[x] = new_hash
another = new_hash
Run Code Online (Sandbox Code Playgroud)

请记住:所有这些任务都只是移动指向对象的指针.现在应该清楚的another是指向新的(空)哈希.但是,由于old_hash 还包含指向新哈希的指针,因此another可以看到对新哈希(即)的任何期货更改old_hash.这就是为什么something每次迭代都会增长的原因.

你的例子与这种简单的情况没什么不同:

x = {}
y = {}
z = {}
x["a"] = y
y["b"] = z
z["c"] = {}
puts x
# {"a"=>{"b"=>{"c"=>{}}}}
Run Code Online (Sandbox Code Playgroud)

您的示例只是反转最后三个分配 - 这对结果没有影响.