Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the point of using Ruby's double-splat (`**`) in method calls?

With a single splat, we can expand an array into multiple arguments, which is pretty different from passing the array directly:

def foo(a, b = nil, c = nil)
  a
end

args = [1, 2, 3]

foo(args)  # Evaluates to foo([1, 2, 3]) => [1, 2, 3]
foo(*args) # Evaluates to foo(1, 2, 3)   => 1

With keyword arguments however, I can't see any difference, since they are just syntactic sugar to hashes:

def foo(key:)
  key
end

args = { key: 'value' }

foo(args)   # Evaluates to foo(key: 'value') => 'value'
foo(**args) # Evaluates to foo(key: 'value') => 'value'

Apart from the nice symmetry, is there any practical reason to use double-splats on method calls? (Note that this is distinct from using them on the method definition)

like image 692
Renato Zannon Avatar asked Mar 26 '14 18:03

Renato Zannon


1 Answers

The example using a single argument is the degenerate case.

Looking at a nontrivial case, you can quickly see the advantage of having the new ** operator:

def foo (args)
  return args
end

h1 = { b: 2 }
h2 = { c: 3 }

foo(a: 1, **h1)       # => {:a=>1, :b=>2}
foo(a: 1, **h1, **h2) # => {:a=>1, :b=>2, :c=>3}
foo(a: 1, h1)         # Syntax Error: syntax error, unexpected ')', expecting =>
foo(h1, h2)           # ArgumentError: wrong number of arguments (2 for 1)

Using the ** operator allows us to merge existing hashes together in the command line, along with literal key-value arguments. (The same is true of using * with argument arrays, of course.)

Sadly, you have to be careful with this behavior, depending on what version of Ruby you're using. In Ruby 2.1.1, at least, there was a bug where the splatted hash would be destructively modified, though it's since been patched.

like image 104
user513951 Avatar answered Nov 16 '22 02:11

user513951