Оператор Double-splat разрушает хэш - это ошибка Ruby?

Я заметил, что я нахожу очень удивительным поведение с оператором ** (double-splat) в Ruby 2.1.1.

Когда пары ключ-значение используются до **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 }

Для сравнения рассмотрим поведение оператора single- * на массивах:

a = [2]

[1, *a]     # => [1, 2]
a           # => [2]

[1, *a, 3]  # => [1, 2, 3]
a           # => [2]

[*a, 3]     # => [2, 3]
a           # => [2]

Массив остается неизменным во всем.


Предположим, что иногда деструктивное поведение ** является преднамеренным, или оно больше похоже на ошибку?

В любом случае, где находится документация, описывающая, как должен работать оператор **?


Я также задал этот вопрос в Ruby Forum.

UPDATE

Исправлена ​​ошибка в Ruby 2.1.3 +.

Ответ 1

Ответы на вопрос выглядят следующим образом:

  • Вероятно, это ошибка, а не намеренная.

  • Поведение оператора ** очень кратко документировано в основной библиотеке rdoc.

Благодаря предложениям нескольких комментаторов, я отправил ошибку в Трекер ошибок в Ruby.


UPDATE:

Исправлена ​​ошибка в changeet r45724. В комментарии было "ключевое слово splat должно быть неразрушающим", что делает этот ответ авторитетным.

Ответ 2

Я заметил разницу между 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 хэш, предоставляемый как двойной знак, переопределяет один и тот же ключ первого элемента в списке.