Ruby Hash: creating a default value for non-existing elements

旧城冷巷雨未停 提交于 2019-12-22 10:52:21

问题


I learned from this answer here that this is possible:

h = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }

h['bar'] # => {}
h['tar']['star']['par'] # => {}

Can someone explain how it works?


回答1:


Hashes have a thing called a default_proc, which is simply a proc that Ruby runs when you try to access a hash key that doesn't exist. This proc receives both the hash itself and the target key as parameters.

You can set a Hash's default_proc at any time. Passing a block parameter to Hash.new simply allows you to initialize a Hash and set its default_proc in one step:

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' }

We can also access the default proc for a hash by calling h.default_proc. Knowing this, and knowing that the ampersand (&) allows a proc passed as a normal parameter to be treated as a block parameter, we can now explain how this code works:

cool_hash = Hash.new{ |h, k| h[k] = Hash.new(&h.default_proc) }

The block passed to Hash.new will be called when we try to access a key that doesn't exist. This block will receive the hash itself as h, and the key we tried to access as k. We respond by setting h[k] (that is, the value of the key we're trying to access) to a new hash. Into the constructor of this new hash, we pass the "parent" hash's default_proc, using an ampersand to force it to be interpreted as a block parameter. This is the equivalent of doing the following, to an infinite depth:

cool_hash = Hash.new{ |h, k| h[k] = Hash.new{ |h, k| h[k] = Hash.new{ ... } } }

The end result is that the key we tried to access was initialized to a new Hash, which itself will initialize any "not found" keys to a new Hash, which itself will have the same behavior, etc. It's hashes all the way down.




回答2:


In this code you create hashes by chain, so that any link of chain would have same default_proc

So, default_proc of h and h['bar'] and so far will be the same - it will return new instance of Hash with this default_proc



来源:https://stackoverflow.com/questions/20158213/ruby-hash-creating-a-default-value-for-non-existing-elements

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!