我从这个答案here中了解到这是可能的:
h = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
h['bar'] # => {}
h['tar']['star']['par'] # => {}
有人可以解释它是如何运作的吗?
答案 0 :(得分:11)
哈希有一个名为default_proc
的东西,它只是当你试图访问一个不存在的哈希键时Ruby运行的一个proc。此proc接收散列本身和目标键作为参数。
您可以随时设置哈希default_proc
。将块参数传递给Hash.new
只是允许您初始化哈希并一步设置其default_proc
:
h = Hash.new
h.default_proc = proc{ |hash, key| hash[key] = 'foo' }
# The above is equivalent to:
h = Hash.new{ |hash, key| hash[key] = 'foo' }
我们还可以通过调用h.default_proc
来访问哈希的默认proc。知道了这一点,并且知道&符号(&
)允许将作为普通参数传递的proc作为块参数处理,我们现在可以解释这段代码是如何工作的:
cool_hash = Hash.new{ |h, k| h[k] = Hash.new(&h.default_proc) }
当我们尝试访问不存在的密钥时,将调用传递给Hash.new
的块。此块将接收哈希本身h
,以及我们尝试以k
访问的密钥。我们通过将h[k]
(即我们尝试访问的密钥的值)设置为新哈希来进行响应。在这个新哈希的构造函数中,我们传递“父”哈希的default_proc
,使用&符号强制它被解释为块参数。这相当于执行以下操作,达到无限深度:
cool_hash = Hash.new{ |h, k| h[k] = Hash.new{ |h, k| h[k] = Hash.new{ ... } } }
最终结果是我们尝试访问的密钥被初始化为一个新的Hash,它本身会将任何“未找到”密钥初始化为一个新的Hash,它本身也会有相同的行为,等等。{{3} }
答案 1 :(得分:1)
在此代码中,您可以按链创建哈希值,以便链的任何链接都具有相同的default_proc
因此,default_proc
和h
的{{1}}到目前为止都是相同的 - 它会返回h['bar']
的新实例Hash