What does a double * (splat) operator do
Asked Answered
F

4

262

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?

Foresail answered 17/8, 2013 at 13:3 Comment(0)
R
474

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}]
Rh answered 17/8, 2013 at 13:11 Comment(4)
This 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}, then foo 10, opts, f: 60 will assign {f: 60} to c, whereas foo 10, **opts, f: 60 will assign {d: 40, e: 50, f: 60}. To achieve the second effect, previously you would have merged the arrays explicitly.Certes
I would assume this is useful for setting optional hash parameters for a methodWaffle
Probably worth a note that if mixing keyword-arguments with keyword splat, the keyword splat needs to come after the keyword arguments.Quita
This does in 10 lines what countless articles fail to do in hundreds. Bravo!Bassarisk
X
53

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.

Xenolith answered 17/8, 2013 at 13:11 Comment(0)
I
41

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}
Indecipherable answered 26/7, 2017 at 22:50 Comment(2)
Wow, double-splat is analagous to ES6's object spread operator.Callant
Thanks, that's the confirmation I was looking for.Ftlb
B
0

For your case, the above answers are accurate.

However, double splat operators can also be used in Ruby language for arithmetic operations as well. For example, x^y can be written as x**y.

Refer to this stackover question for more.

Biconvex answered 13/6, 2022 at 5:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.