22

Ruby has differences between Procs created via Proc.new and lambda (or the ->() operator in 1.9). It appears that non-lambda Procs will splat an array passed in across the block arguments; Procs created via lambda do not.

p = Proc.new { |a,b| a + b}
p[[1,2]] # => 3

l = lambda { |a,b| a + b }
l[[1,2]] # => ArgumentError: wrong number of arguments (1 for 2)

Does anyone have any insight into the motivations behind this behavior?

sawa
  • 165,429
  • 45
  • 277
  • 381
Brian
  • 285
  • 2
  • 8

1 Answers1

39

There are two main differences between lambdas and non-lambda Procs:

  1. Just like methods, lambdas return from themselves, whereas non-lambda Procs return from the enclosing method, just like blocks.
  2. Just like methods, lambdas have strict argument checking, whereas non-lambda Procs have loose argument checking, just like blocks.

Or, in short: lambdas behave like methods, non-lambda Procs behave like blocks.

What you are seeing there is an instance of #2. Try it with a block and a method in addition to a non-lambda Proc and a lambda, and you'll see. (Without this behavior, Hash#each would be a real PITA to use, since it does yield an array with two-elements, but you pretty much always want to treat it as two arguments.)

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • 1
    Thanks for the quick response. Has#each / #sort was how I came across this in the first place. I ended up using the following syntax to avoid the verbosity of Proc.new: ->((a,b)) { ... } – Brian Jan 26 '11 at 00:39