What does a double * (splat) operator do
Solution 1
Ruby 2.0 introduced keyword arguments, and **
acts like *
, but for keyword arguments. It returns a Hash with key / value pairs.
For this code:
def foo(a, *b, **c)
[a, b, c]
end
Here's a demo:
> foo 10
=> [10, [], {}]
> foo 10, 20, 30
=> [10, [20, 30], {}]
> foo 10, 20, 30, d: 40, e: 50
=> [10, [20, 30], {:d=>40, :e=>50}]
> foo 10, d: 40, e: 50
=> [10, [], {:d=>40, :e=>50}]
Solution 2
That is the double splat operator which is available since Ruby 2.0.
It captures all keyword arguments (which can also be a simple hash, which was the idiomatic way to emulate keyword arguments before they became part of the Ruby language)
def my_method(**options)
puts options.inspect
end
my_method(key: "value")
The above code prints {key:value}
to the console.
Just like the single splat operator captures all regular arguments, but instead of an array you get a hash.
Real-life example:
For example in Rails the cycle
method looks like this:
def cycle(first_value, *values)
options = values.extract_options!
# ...
end
This method can be called like this: cycle("red", "green", "blue", name: "colors")
.
This is quite a common pattern: You accept a list of arguments and the last one is an options hash, which can be extract - for example - using ActiveSupport's extract_options!
.
In Ruby 2.0 you can simplify these methods:
def cycle(first_value, *values, **options)
# Same code as above without further changes!
end
Admittedly it's only a minor improvement if you are already using ActiveSupport but for plain Ruby the code gains quite a lot of conciseness.
Solution 3
In addition, you can use it in caller side like this:
def foo(opts); p opts end
bar = {a:1, b:2}
foo(bar, c: 3)
=> ArgumentError: wrong number of arguments (given 2, expected 1)
foo(**bar, c: 3)
=> {:a=>1, :b=>2, :c=>3}
Related videos on Youtube
Roy Lee
Updated on July 27, 2020Comments
-
Roy Lee almost 4 years
Have you seen a function declared like this?
def foo a, **b ... end
I understand that a single
*
is the splat operator. What does**
mean? -
brymck over 10 yearsThis answers the question perfectly, but I had a minor addendum. Just as the splat operator can be used on the array you pass, the double splat can be used on hashes. If
opts = {d: 40, e: 50}
, thenfoo 10, opts, f: 60
will assign{f: 60}
toc
, whereasfoo 10, **opts, f: 60
will assign{d: 40, e: 50, f: 60}
. To achieve the second effect, previously you would havemerge
d the arrays explicitly. -
bigpotato over 10 yearsI would assume this is useful for setting optional hash parameters for a method
-
MrMesees about 5 yearsProbably worth a note that if mixing keyword-arguments with keyword splat, the keyword splat needs to come after the keyword arguments.
-
mpoisot about 5 yearsWow, double-splat is analagous to ES6's object spread operator.
-
Qortex over 4 yearsThanks, that's the confirmation I was looking for.