Оператор двойных сплатов деструктивно модифицирует хеш - это ошибка Ruby?
Я заметил очень удивительное поведение с **
(двойной сплат) оператор в 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 }
Для сравнения рассмотрим поведение*
оператор по массивам:
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+.
2 ответа
Ответы на вопрос выглядят так:
Это скорее ошибка, чем преднамеренная.
Поведение
**
Оператор очень кратко документирован в основной библиотеке rdoc.
Благодаря предложениям нескольких комментаторов, я разместил сообщение об ошибке в трекере проблем с хоботом Ruby.
ОБНОВИТЬ:
Ошибка была исправлена в ревизии r45724. Там было замечание "сплат ключевых слов должен быть неразрушающим", что делает его авторитетным ответом.
Я заметил разницу между 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 хэш, представленный в виде двойного восклицательного знака, переопределяет тот же ключ первого элемента в списке.