Ruby Hash:为不存在的元素创建默认值

我在这里从这个答案中了解到这是可能的:

h = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) } h['bar'] # => {} h['tar']['star']['par'] # => {} 

有人能解释它是如何工作的吗?

哈希有一个叫做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,它本身也会有相同的行为,等等。 它一直是哈希。

在此代码中,您可以按链创建哈希,以便链的任何链接都具有相同的default_proc

所以, hh['bar'] default_proc和目前为止是相同的 – 它将使用此default_proc返回Hash新实例