Blocs, procs and lambdas in Ruby

Can you repeat please?

July 21st, 2015

Blocks, procs and lambdas are different types of closures in Ruby. In human language it simply refers to ways of repeating code. Blocks are usually well understood but procs and lambdas can be more mysterious. Hopefully this little explanation will help.

Blocs

They allow us to apply a specific code to a series of elements. They are recognizable under 2 forms, using {} or do…end.

array = [1, 2, 3, 4]

array.cycle do |n|
  n*2
end

# => [1, 4, 6, 8]

So, what happens here?

  1. First, we send the cycle method to an Array with a block of code (you remember the cycle method, right?)
  2. The code block interacts with a variable used within the cycle method (n in this case) and multiple it by 2.
  3. Each element inside the array is now doubled.

Procs

Blocs are great but what if we want to use the same bloc in several parts of a well-respected DRY code? We use procs! Procs are like blocks but can be saved and reused later in the code.

array = [1, 2, 3, 4]

p = Proc.new { |n| puts n*2 }

array.each(&p)

# => [1, 4, 6, 8]

So, what happens here?

  1. First, we create a proc using Proc.new and write the block to be saved.
  2. The proc is then called on a method using &p.
  3. Each element inside the array is now doubled.

Lambdas

Procs and lambdas are very similar and are often used interchangeably. There are 2 main differences between both. First, procs do not check for the number of arguments when lambdas do, here is how it looks:

lam = lambda { |x| puts x }
proc = Proc.new { |x| puts x }

lam.call(1)                # prints out 1
proc.call(1)               # prints out 1

lam.call                   # ArgumentError: wrong number of arguments (0 for 1)
proc.call                  # returns nil

lam.call(1,2,3)            # ArgumentError: wrong number of arguments (3 for 1)
proc.call(1,2,3)           # prints out 1 and forgets about the extra arguments

The second difference is that procs and lambdas treat return differently. While proc return will only work at the first method and return the value provided, lambdas will return their value and continue through the rest of the code.

def lambda
  lambda { return "Block string" }.call
  return "method is finished"
end

def proc
  Proc.new { return "Block string"}.call
  return "method is finished"
end

puts lambda          # => Block string
puts proc            # => method is finished

This second difference makes procs more difficult to work with than lambdas, Ruby experts usually recommend working with the latter. I’m writing about these concepts as I’m learning about them, so as usual any feedback is more than welcome!