Thursday, April 28, 2011

What's the difference between a proc and a lambda in Ruby?

And when would you use one rather than the other?

From stackoverflow
  • The only difference is in the way they handle arguments. Creating a proc using proc {} and {} are equivalent. However, using lambda {} gives you a proc that checks the number of arguments passed to it. From ri Kernel#lambda:

    Equivalent to, except the resulting Proc objects check the number of parameters passed when called.

    An example:

    p = {|a, b| puts a**2+b**2 } # => #<Proc:0x3c7d28@(irb):1> 1, 2 # => 5 1 # => NoMethodError: undefined method `**' for nil:NilClass 1, 2, 3 # => 5
    l = lambda {|a, b| puts a**2+b**2 } # => #<Proc:0x15016c@(irb):5 (lambda)> 1, 2 # => 5 1 # => ArgumentError: wrong number of arguments (1 for 2) 1, 2, 3 # => ArgumentError: wrong number of arguments (3 for 2)

    In addition, as Ken points out, using return inside a lambda returns the value of that lambda, but using return in a proc returns from the enclosing block.

    lambda { return :foo }.call # => :foo
    return # => LocalJumpError: unexpected return { return :foo }.call # => LocalJumpError: unexpected return

    So for most quick uses they're the same, but if you want automatic strict argument checking (which can also sometimes help with debugging), or if you need to use the return statement to return the value of the proc, use lambda.

    OscarRyz : +1 For the sample code
    James Thompson : Good article to follow up on this:
  • In addition to jtbandes's answer, there's also a difference in what the return statement returns from in proc versus lambda.

    jtbandes : Good point. I added this to my answer.
    tadman : I also can't wait for something equivalent to "Ruby 3000" to fix this. This distinction is way too subtle.
  • It's somewhat subtle. They're both methods that create closures, and both return Proc objects. There's actually a third way as well — The difference is in how they behave, and the specifics depend on whether you're using Ruby 1.8 or 1.9 (in fact, there's yet another way to create them in Ruby 1.9). In the general case, the difference isn't something you need to worry about. Only when you're concerned about strictness does it make a difference. This SO question covers the differences pretty well.


Post a Comment