Why does Hash.new({}) hide hash members? [duplicate]

∥☆過路亽.° 提交于 2019-11-30 01:40:26

问题


Ok, so I wanted to create a hash which has an empty hash as the default value. A bit weird, I know, but let's say that I thought it might be useful.

So here's what I did:

>> a = Hash.new({})
=> {}
>> a[:a][:b] = 5
=> 5
>> a
=> {}
>> a[:a]
=> {:b=>5}
>> a.keys
=> []
>> a.size
=> 0
>> a[:a].size
=> 1

In other words, I don't see hash member when I inspect the hash, but I can access it by its key.

Is this expected behavior? What is going on here?

BTW, this is Ruby 1.9.1, haven't tried earlier versions.

Edit: simplified example as it doesn't have to be a hash of hashes of hashes...


回答1:


It is expected behaviour (across all ruby versions). And if you experiment a bit further, you'll see that you always access the same hash, no matter which key you use:

>> a[:a][:b] = 1
=> 1
>> a[:c][:d] = 2
=> 2
>> a[:d]
=> {:b=>1, :d=>2}

The way Hash.new with a default argument works is: If you do hash[key] it checks whether that key exists in the hash. If it does, it returns the value for that key. If not it returns the default value. It does not add the key to the hash and it will return the same default object (not a copy) every time.

To get what you want, you want to specify a default block instead. That way, the block will be executed every time you access a key that is not in the hash. Inside the block you can create a new Hash and set the key to "point" to that hash. Like so:

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


来源:https://stackoverflow.com/questions/1822021/why-does-hash-new-hide-hash-members

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