灵感来自我如何用数组编组哈希?我想知道Array#<<在以下代码中无法正常工作的原因是什么:
h = Hash.new{Array.new}
#=> {}
h[0]
#=> []
h[0] << 'a'
#=> ["a"]
h[0]
#=> [] # why?!
h[0] += ['a']
#=> ["a"]
h[0]
#=> ["a"] # as expected
Run Code Online (Sandbox Code Playgroud)
它是否与<<在就地更改数组的事实有关,同时Array#+创建了一个新实例?
Jör*_*tag 33
如果Hash使用块形式创建Hash.new,则每次尝试访问实际不存在的元素时都会执行块.那么,让我们看看会发生什么:
h = Hash.new { [] }
h[0] << 'a'
Run Code Online (Sandbox Code Playgroud)
这里评估的第一件事就是表达式
h[0]
Run Code Online (Sandbox Code Playgroud)
评估后会发生什么?好吧,块运行:
[]
Run Code Online (Sandbox Code Playgroud)
这不是很令人兴奋:块只是创建一个空数组并返回它.它没有做任何其他事情.特别是,它不会h以任何方式改变:h仍然是空的.
接下来,<<带有一个参数的消息'a'被发送到结果,h[0]该结果是块的结果,这只是一个空数组:
[] << 'a'
Run Code Online (Sandbox Code Playgroud)
这是做什么的?它将元素添加'a'到空数组中,但由于数组实际上并未分配给任何变量,因此它会立即被垃圾收集并消失.
现在,如果h[0]再次评估:
h[0] # => []
Run Code Online (Sandbox Code Playgroud)
h仍然是空的,因为没有任何东西被分配给它,因此密钥0仍然不存在,这意味着块再次运行,这意味着它再次返回一个空数组(但请注意,它是一个全新的,不同的空数组现在).
h[0] += ['a']
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?首先,操作员分配变得卑鄙
h[0] = h[0] + ['a']
Run Code Online (Sandbox Code Playgroud)
现在,h[0]在右侧边被评估.它又回归了什么?我们已经讨论了这个:h[0]不存在,因此块运行,块返回一个空数组.同样,这是一个全新的第三个空数组.这个空数组被发送+带有参数的消息['a'],这导致它返回另一个新数组,即数组['a'].然后将此数组分配给h[0].
最后,在这一点上:
h[0] # => ['a']
Run Code Online (Sandbox Code Playgroud)
现在你终于实际上放了一些东西h[0],显然,你得到了你投入的东西.
所以,为了回答你可能有的问题,你为什么不把它放进去?你没有把任何东西放在首位!
如果你真的想要分配给块内的哈希,你必须分配给块内的哈希:
h = Hash.new {|this_hash, nonexistent_key| this_hash[nonexistent_key] = [] }
h[0] << 'a'
h[0] # => ['a']
Run Code Online (Sandbox Code Playgroud)
如果你查看所涉及对象的身份,实际上很容易看到你的代码示例中发生了什么.然后你可以看到每次调用时h[0],你会得到一个不同的数组.
| 归档时间: |
|
| 查看次数: |
1437 次 |
| 最近记录: |