双splat运算符破坏性地修改哈希 – 这是一个Ruby错误吗?
我注意到我发现Ruby 2.1.1中的**
(双splat)运算符是一个非常令人惊讶的行为。
在**hash
之前使用键值对时,哈希保持不变; 但是,当键值对仅在**hash
之后使用时,哈希值将被永久修改。
h = { b: 2 } { a: 1, **h } # => { a: 1, b: 2 } h # => { b: 2 } { a: 1, **h, c: 3 } # => { a: 1, b: 2, c: 3 } h # => { b: 2 } { **h, c: 3 } # => { b: 2, c: 3 } h # => { b: 2, c: 3 }
为了进行比较,请考虑单个*
运算符在数组上的行为:
a = [2] [1, *a] # => [1, 2] a # => [2] [1, *a, 3] # => [1, 2, 3] a # => [2] [*a, 3] # => [2, 3] a # => [2]
arrays始终保持不变。
我们是否认为**
的有时破坏性行为是有意的,还是看起来更像是一个错误?
在任何一种情况下,描述**
运算符如何工作的文档在哪里?
我也在Ruby论坛中问过这个问题。
UPDATE
该错误已在Ruby 2.1.3+中修复。
这个问题的答案似乎是:
-
这可能是一个错误,而不是故意的。
-
**
运算符的行为在核心库rdoc中非常简要地记录 。
感谢几位评论者的建议,我已将错误发布到Ruby trunk问题跟踪器 。
更新:
该错误已在changeset r45724中修复 。 那里的评论是“ 关键字splat应该是非破坏性的 ”,这使得这是一个权威的答案。
我注意到2.1.5和2.3.1之间的差异
示例是irb方法和调用它的方法
$ irb >> def foo(opts) opts end => :foo >> foo a: 'a', ** {a: 'b'}
在2.1.5中,以下结果保留了价值
=> {:a=>"a"}
在2.3.1中,值为’b’
(irb):2: warning: duplicated key at line 2 ignored: :a => {:a=>"b"}
我不确定它应该是什么?
在2.3.1中,以double splat提供的哈希覆盖列表中第一项的相同键。