I noticed what I find to be a very surprising behavior with the **
(double-splat) operator in Ruby 2.1.1.
When key-value pairs are used before a **hash
, the hash remains unmodified; however, when key-value pairs are only used after the **hash
, the hash is permanently modified.
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 }
For comparison, consider the behavior of the single-*
operator on arrays:
a = [2]
[1, *a] # => [1, 2]
a # => [2]
[1, *a, 3] # => [1, 2, 3]
a # => [2]
[*a, 3] # => [2, 3]
a # => [2]
The array remains unchanged throughout.
Do we suppose the sometimes-destructive behavior of **
is intentional, or does it look more like a bug?
In either case, where is the documentation describing how the **
operator is meant to work?
I also asked this question in the Ruby Forum.
UPDATE
The bug is fixed in Ruby 2.1.3+.
h
andi
and do{**h, **i, d: 5}
, onlyh
is modified, noti
. – Charlinecharlockh
, but there's also more to it. Considerh = { a: 1 }; { **h, a: 99, **h }
. Since the final result is{ a: 99 }
, we can see that even by the time we reach the final**h
,h[:a]
has already been overwritten. – Debug