Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

ruby

And when would you use one rather than the other?

like image 762
Tom Lehman Avatar asked Nov 16 '09 04:11

Tom Lehman


People also ask

What is a Proc in Ruby?

A Proc object is an encapsulation of a block of code, which can be stored in a local variable, passed to a method or another Proc, and can be called. Proc is an essential concept in Ruby and a core of its functional programming features.

What does lambda do in Ruby?

Ruby lambdas allow you to encapsulate logic and data in an eminently portable variable. A lambda function can be passed to object methods, stored in data structures, and executed when needed. Lambda functions occupy a sweet spot between normal functions and objects.

What is the difference between PROC and block?

Procs are objects, blocks are notA proc (notice the lowercase p) is an instance of the Proc class. This lets us call methods on it and assign it to variables. Procs can also return themselves. In contrast, a block is just part of the syntax of a method call.


1 Answers

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

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

An example:

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

like image 133
jtbandes Avatar answered Sep 22 '22 06:09

jtbandes