Zauważyłem, co uważam za bardzo zaskakujące zachowanie z operatorem **
(double-splat) w Ruby 2.1.1.Operator z podwójnym splatem destruktywnie modyfikuje hash - czy jest to błąd Ruby?
Gdy pary klucz-wartość są używane przed **hash
, skrót jest niezmieniony; jednak gdy pary klucz-wartość są używane tylko po **hash
, skrót jest trwale zmodyfikowany.
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 }
Dla porównania, za zachowanie jedno- *
operatora na tablicach:
a = [2]
[1, *a] # => [1, 2]
a # => [2]
[1, *a, 3] # => [1, 2, 3]
a # => [2]
[*a, 3] # => [2, 3]
a # => [2]
Tablica pozostaje bez zmian w całym tekście.
Czy sądzimy niekiedy destrukcyjne zachowanie **
jest zamierzone, czy to wygląda bardziej jak robaka?
W obu przypadkach, gdzie jest dokumentacja opisująca działanie operatora **
?
Też zapytałem to pytanie in the Ruby Forum.
UPDATE
Błąd jest stała w Ruby 2.1.3+.
Użycie na listach parametrów znajduje się w głównej dokumentacji http://www.ruby-doc.org/core-2.1.1/doc/syntax/methods_rdoc.html. Hash i tablica interpolacja nie wydają się pojawiać nigdzie tam, chociaż single spat przynajmniej ma spec: https://github.com/rubyspec/rubyspec/blob/master/language/splat_spec.rb. Nie ma nic podobnego do podwójnej kłótni. Semantyka ruby wydaje się folklorystyczna. Jestem pewien, że to jest błąd, ponieważ nieudokumentowana funkcja językowa może być błędna! – Gene
Nie wiedziałem nawet, że możesz używać tego w podpisie metody none ... – phoet
Wygląda na to, że skompilowany skrót jest tym samym obiektem, co pierwszy element w nim, jeśli jest hash (mają one ten sam identyfikator obiektu). Właśnie dlatego są one modyfikowane. Kiedy masz dwa hashe 'h' i' i' oraz '' '**, **, d: 5}', modyfikowane jest tylko 'h', a nie' i'. – sawa