双splat操作符破坏性地修改了hash——这是Ruby的bug吗



我注意到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+中修复。

问题的答案似乎是:

  1. 这可能是一个错误,而不是故意的。

  2. 核心库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提供的散列覆盖列表中第一个项目的相同密钥。

相关内容

  • 没有找到相关文章

最新更新