Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does yielding to lambda splat array arguments in Ruby?

Tags:

yield

ruby

lambda

In Ruby, calling a lambda with the wrong number of arguments results in an ArgumentError:

l = lambda { |a, b| p a: a, b: b }
l.call(1, 2) 
# {:a=>1, :b=>2}

l.call(1)
# ArgumentError: wrong number of arguments (given 1, expected 2)

Passing an array instead doesn't work either: (because an array is just a single object, right?)

l.call([3, 4])
# ArgumentError: wrong number of arguments (given 1, expected 2)

Unless I use a splat (*) to convert the array to an argument list, but I didn't.

But ... if I call the lambda implicitly via yield, something unexpected happens:

def yield_to
  yield(1, 2)
  yield([3, 4])
end

yield_to(&l)
# {:a=>1, :b=>2}
# {:a=>3, :b=>4}   <- array as argument list!?

What's even more confusing, a lambda derived via Method#to_proc does work as expected:

def m(a, b)
  p a: a, b: b
end

yield_to(&method(:m))
# {:a=>1, :b=>2}
# ArgumentError: wrong number of arguments (given 1, expected 2)

What's going on here?

like image 861
Stefan Avatar asked Jan 26 '17 09:01

Stefan


1 Answers

I'm answering my own question here, because this is a known bug:

https://bugs.ruby-lang.org/issues/12705

And it was fixed in Ruby 2.4.1 (thanks @ndn)

like image 173
Stefan Avatar answered Sep 30 '22 18:09

Stefan