10

我注意到我发现**Ruby 2.1.1 中的 (double-splat) 运算符有一个非常令人惊讶的行为。

当在 a 之前使用键值对时**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]

数组始终保持不变。


我们是否认为有时具有破坏性的行为**是故意的,还是看起来更像是一个错误?

无论哪种情况,描述**操作员如何工作的文档在哪里?


我也在Ruby 论坛上问过这个问题。

更新

该错误已在 Ruby 2.1.3+ 中修复。

4

2 回答 2

7

这个问题的答案似乎是:

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

  2. 操作员的行为在核心库 rdoc**中有非常简短的记录。

感谢几位评论者的建议,我已将该错误发布到Ruby 主干问题跟踪器


更新:

该错误已在变更集 r45724中修复。那里的评论是“关键字 splat 应该是非破坏性的”,这使得这是一个权威的答案。

于 2014-04-25T20:22:39.147 回答
1

我注意到 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 提供的散列会覆盖列表中第一项的相同键。

于 2016-07-27T18:05:30.707 回答