Why do Ruby (2.0) procs/blocks with splat arguments behave differently than methods and lambdas?
def foo (ids, *args)
p ids
end
foo([1,2,3]) # => [1, 2, 3]
bar = lambda do |ids, *args|
p ids
end
bar.call([1,2,3]) # => [1, 2, 3]
baz = proc do |ids, *args|
p ids
end
baz.call([1,2,3]) # => 1
def qux (ids, *args)
yield ids, *args
end
qux([1,2,3]) { |ids, *args| p ids } # => 1
Here's a confirmation of this behavior, but without explanation: http://makandracards.com/makandra/20641-careful-when-calling-a-ruby-block-with-an-array
There are two types of
Proc
objects:lambda
which handles argument list in the same way as a normal method, andproc
which use "tricks" (Proc#lambda?).proc
will splat an array if it's the only argument, ignore extra arguments, assignnil
to missing ones. You can partially mimicproc
behavior withlambda
using destructuring:Just encountered a similar issue!
Anyways, my main takeaways:
The splat operator works for array assignment in a predictable manner
Procs effectively assign arguments to input (see disclaimer below)
This leads to strange behavior, i.e. the example above:
So what's happening?
[1,2,3]
gets passed tobaz
, which then assigns the array to its argumentsWhen run, the block only inspects
ids
, which is1
. In fact, if you insertp args
into the block, you will find that it is indeed[2,3]
. Certainly not the result one would expect from a method (or lambda).Disclaimer: I can't say for sure if Procs simply assign their arguments to input under the hood. But it does seem to match their behavior of not enforcing the correct number of arguments. In fact, if you give a Proc too many arguments, it ignores the extras. Too few, and it passes in nils. Exactly like variable assignment.