If you’ve been learning how to develop software in Ruby, you are probably familiar with blocks (closures). Blocks are statements that are fed into method calls as arguments which then executes those statements. Here’s an example of a block given to a popular ruby method.
[1, 2, 3].each {|x| puts x}
[1, 2, 3].each do |x|
puts x
end
In this post, we’re going to introduce Proc and lambdas. A Proc is similar to a block in that it also is a statement or statements, but unlike a block which are like anonymous functions, Proc
is a ruby class and new procs are instances of the class.
new_proc = Proc.new {|x| puts x} # => #<Proc:0x007fd9a080e450@(irb):1>
new_proc.call('Hello World') # Hello World
new_proc.class # => Proc
As you can see, we create a new Proc object that defines a block of code. We call the proc with call
and supply it with an argument 'Hello World'
which is then passed on the block defined by the proc.
Similar to a proc, ruby also has lambda
. A lambda is a special kind of Proc
. One of the differences between a lambda and a regular proc is that a lambda have argument number restrictions. A proc can be supplied with more arguments than required, but lambda’s will throw errors that the number of arguments is off.
new_lamdba = lambda {|x| puts x} # => #<Proc:0x007fd99f8a65f8@(irb):4 (lambda)>
new_lamdba.class # => Proc
new_lamdba.call('Hello World') # => Hello World
new_proc('hello world', 'foobar') # => hello world
new_lamdba('hello world', 'foobar') # ArgumentError: wrong number of arguments (2 for 1)
Another key difference with proc and lambda is that returns work a little differently in each. Lambda returns from it self while procs returns from the method. Lets check this behavior with some examples
def lambda_returns
l = lambda { return 'foobar'}
l.call # returns foobar from the call and continues to the next line
puts 'Hello World'
end
lambda_returns # Hello World => nil
And the same as a proc
def proc_returns
p = Proc.new { return 'foobar'}
p.call
puts 'Hello World' # shouldn't get hit because Proc already returned foobar
end
proc_returns # => nil
In my next post, I’ll go into how Procs and lambdas can be used to pass data between scopes.