考虑以下代码:h = Hash.new(0) # 新的哈希对默认将具有 0 作为值h[1] += 1 #=> {1=>1}h[2] += 2 #=> {2=>2} 这些都很好,但是:h = Hash.new([]) # 空数组...
考虑以下代码:
h = Hash.new(0) # New hash pairs will by default have 0 as values
h[1] += 1 #=> {1=>1}
h[2] += 2 #=> {2=>2}
这一切都很好,但是:
h = Hash.new([]) # Empty array as default value
h[1] <<= 1 #=> {1=>[1]} ← Ok
h[2] <<= 2 #=> {1=>[1,2], 2=>[1,2]} ← Why did `1` change?
h[3] << 3 #=> {1=>[1,2,3], 2=>[1,2,3]} ← Where is `3`?
此时我期望哈希值为:
{1=>[1], 2=>[2], 3=>[3]}
但事实并非如此。发生了什么事?我怎样才能获得我期望的行为?
运算符 +=
应用于这些哈希值时,它会按预期工作。
[1] pry(main)> foo = Hash.new( [] )
=> {}
[2] pry(main)> foo[1]+=[1]
=> [1]
[3] pry(main)> foo[2]+=[2]
=> [2]
[4] pry(main)> foo
=> {1=>[1], 2=>[2]}
[5] pry(main)> bar = Hash.new { [] }
=> {}
[6] pry(main)> bar[1]+=[1]
=> [1]
[7] pry(main)> bar[2]+=[2]
=> [2]
[8] pry(main)> bar
=> {1=>[1], 2=>[2]}
这可能是因为 foo[bar]+=baz
当 foo[bar]=foo[bar]+baz
右边的 foo[bar]
被求值时,它返回 =
默认值 对象,并且 运算符不会改变它。左边是方法的语法糖, +
它 []=
不会改变 默认值 .
请注意,这不适用于, foo[bar]<<=baz
因为它相当于 foo[bar]=foo[bar]<<baz
并将 <<
更改 默认 值 .
另外,我发现 Hash.new{[]}
和 Hash.new{|hash, key| hash[key]=[];}
。至少在 ruby 2.1.2 上是这样。