我注意到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]
数组始终保持不变。
我们认为**
有时的破坏性行为是故意的,还是看起来更像一个bug?
在任何一种情况下,描述**
操作员如何工作的文档在哪里?
我在Ruby论坛上也问过这个问题。
更新
该错误已在Ruby 2.1.3+中修复。
问题的答案似乎是:
-
这可能是一个错误,而不是故意的。
-
核心库rdoc中简要地记录了
**
运算符的行为。
感谢几位评论者的建议,我已经将这个bug发布到了Ruby trunk问题跟踪器上。
更新:
该错误已在变更集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中,作为双splat提供的散列覆盖列表中第一个项目的相同密钥。