2015-10-08 50 views
1

我想知道为什么a在下面是a[:a]后空哈希被称为,这是不是空:使用嵌套哈希和哈希为默认值没有按预期工作

a = Hash.new({a:1}) # => {} 
a[:a][:a] += 1  # => 2 
a     # => {} 
a[:a]    # => {:a=>2} 

我知道{a: 1}在每个不存在的密钥之间共享(a[:something_inexistent])。但为什么它不显示为a的关键?如果可能的话,使用Ruby的内部将非常感激。

+1

'{a:1}'是默认的*值*,所以如果'a'没有键'k','a [k]'返回'{a:1}'但它不会改变散列。如果你想改变哈希,'a [:k] = a [:k]; a#=> {:k => {:a => 1}}'。对于一个数值为散列的变量,'h'会比'a'更好,就像数组'a'会比'h'好。 –

+0

我最近看了一篇文章,可能会有所帮助:[Bottomless Ruby Hash](http://firedev.com/posts/2015/bottomless-ruby-hash/) – ShallmentMo

回答

4

这是因为a[:a]从来没有分配。当您执行a[:a]时,它不会返回存储的值,而是返回默认值。

与此不同,当你不是有:

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

然后,每当缺少键被调用时,该块被执行,其值分配给键,a将不再是一个空哈希。

+0

为什么传递'{a:1}到'Hash.new'设置默认值为1,但?这似乎有点奇怪。 –

+0

我认为他的一部分混乱是'a = Hash.new({a:1})'不同于'a = {a:1}'。我知道,当我第一次看到它的时候就知道了。 – Beartech

+0

啊,我想我现在从看[API](http://docs.ruby-lang.org/en/2.2.0/Hash.html#method-c-new)就能理解了。看看他们是如何传递“Go Fish”作为参数的,然后调用'h [“c”]'并返回“Go Fish”?当密钥不存在时,他设置默认值为另一个内部哈希{{a:1}'。当他执行'+ = 1'命令时,他实际上正在改变默认值,现在是'{a:2}',但从未将其分配给任何键,因此主散列仍为空。 –