Blocks, Procs and lambdas also known as closures in Computer Science are one of the most powerful aspects of Ruby, and also one of the most misunderstood. I will attempt to explains the similarities and differences.

First Up Blocs

A block is just a bit of code between do..end or {}. It’s not an object on its own, but it can be passed to methods like .each or .collect.

We’ve seen this in action.

array = [1, 2, 3, 4]
 
array.collect! do |n|
  n ** 2
end
 
puts array.inspect      # => [1, 4, 9, 16]

Nothing new here.

Now Procs

A proc is a saved block we can use over and over. Just like you can give a bit of code a name and turn it into a method, you can name a block and turn it into a proc. With procs you write your code once and use it many times. That way keeping your code D.R.Y (Don’t Repeat Yourself).

cube = Proc.new { |x| x ** 3 }
 
[1, 2, 3].collect!(&cube)    #=>[ 1, 8, 27]
  
[4, 5, 6].map!(&cube)       #=>[64, 125, 216]

Last, but not least, Lambdas

Like procs lambdas are objects. With the exception of some syntax differences, procs and lamdas are essentially the same.

mbda { puts "Hello!" }
 
 #Is just about the same as
  
Proc.new { puts "Hello!" }

Lambdas vs. Procs

Eventhough procs and lambdas sport stricking similarities there are two main differences.

First, lambdas check the number of arguments, while procs do not.

lam = lambda { |x| puts x }    # creates a lambda that takes 1 argument
lam.call(2)                    # prints out 2
lam.call                       # ArgumentError: wrong number of arguments (0 for 1)
lam.call(1,2,3)                # ArgumentError: wrong number of arguments (3 for 1)

In contrast, procs don’t care if they are passed the wrong number of arguments.

proc = Proc.new { |x| puts x } # creates a proc that takes 1 argument
proc.call(2)                   # prints out 2
proc.call                      # returns nil
proc.call(1,2,3)               # prints out 1 and forgets about the extra arguments

Second, Lambdas and procs treat the ‘return’ keyword differently.

‘return’ inside of a lambda triggers the code right outside of the lambda code

def lambda_test
  lam = lambda { return }
  lam.call
  puts "Hello world"
end
 
lambda_test  # calling lambda_test prints 'Hello World'

‘return’ inside of a proc triggers the code outside of the method where the proc is being executed

def proc_test
  proc = Proc.new { return }
  proc.call
  puts "Hello world"
end
 
proc_test  # calling proc_test prints nothing

Summary Differences

  1. Procs are objects, blocks are not
  2. A proc is a saved block we can use over and over.
  3. A lambda is just like a proc, only it cares about the number of arguments it gets and it returns to its calling method rather than returning immediately.