Ruby — Proc, Block & Lambda — What’s the Confusion?

Lakhveer Singh Rajput
4 min readJun 27, 2024

--

In this article, we will understand about the block, proc, and lambda in Ruby. After going through the article we would know better about what they are, how they work, and what are the differences or similarities between them.

Block — Simply Solved😌

Blocks are a small anonymous function passed into a method. So don’t get confused they are just a few lines of code enclosed either into brackets ({}) or do-end passed into the method as an argument and called in the method through using the yield keyword. Let’s see an example:

def simple_block
puts "Inside Method"
yield 1
yield 2
puts "After the Block Call"
end

simple_block { |a| puts "Hey Block Called #{a} time" }
# Inside Method
# Hey Block Called 1 time
# Hey Block Called 2 time
# After the Block Call

# Explicit Block used as variable
def simple_block(&name)
puts "Inside Method"
yield 1
yield 2
name.call(3)
puts "After the Block Call"
end

simple_block { |a| puts "Hey Block Called #{a} time" }

# Inside Method
# Hey Block Called 1 time
# Hey Block Called 2 time
# Hey Block Called 3 time
# After the Block Call

From the above example, it might be very clear how the block actually works. We passed the block in the method in two ways — Explicit(using a variable name) and Implicit(directly without a name).

Proc — The major Class🤔

Procs are similar to blocks in working but they can be assigned to a variable where blocks cannot be assigned to a variable. To make it more clear when we see the block class, it tends to belong to the Proc class. This means it’s clear that all blocks, either simple Block, Proc Instance, or Lambda, belong to the same class that is Proc. Let us first see the Proc with example:

def proc_blocks(proc_block)
puts "Inside Method"
# Different types we call a Proc
proc_block.call 1
proc_block.(2)
proc_block.[] 3
proc_block.===4
# Yield can't be used as Block been passed as a variable not Block
puts "After Block Call"
end

p1 = Proc.new { |a| puts "Hey Block Called #{a} time" }
proc_blocks(p1)

# Inside Method
# Hey Block Called 1 time
# Hey Block Called 2 time
# Hey Block Called 3 time
# Hey Block Called 4time
# After the Block Call

def simple_block(&name)
puts "Inside Method"
puts name.class
puts "After the Block Call"
end

simple_block { |a| puts "Hey Block Called #{a} time" }

# Inside Method
# Proc
# After the Block Call

In this example, it had been clear that the block is an instance of the Proc directly.

Lambda — Why another way?🤔

Lambda is also the instance of the Proc class which has its own syntax to be defined. Lamda can also be assigned to a variable and can be called the same as Proc. Let’s first get through lambda syntax and example, then we will know the difference between them:

def lambda_blocks(lambda_block)
puts "Inside Method"
# Different types we call a Lambda
lambda_block.call 1
lambda_block.(2)
lambda_block.[] 3
lambda_block.===4
# Yield can't be used as Block been passed as a variable not Block
puts "After Block Call"
end

p1 = -> (a) { puts "Hey Block Called #{a} time" }
lambda_blocks(p1)

# Inside Method
# Hey Block Called 1 time
# Hey Block Called 2 time
# Hey Block Called 3 time
# Hey Block Called 4time
# After the Block Call

It’s weird if lambda, Block, and Proc are the same why do we have different versions same block functionality?

Not Same At All— Let’s see

  1. Proc and Block do not care about the arguments passed, while lambda throws an Argument error whenever the wrong number of arguments are passed.
  2. If a Proc contains a return it will return the whole method from the same place without performing the rest of the method code while lambda returns from itself and performs the rest of the method code.
lambda_block = -> (a){   puts "Hey Block Called #{a} time" }
lambda_block.call
# Throws error- wrong number of Arguments

proc_block = Proc.new { |a| puts "Hey Block Called #{a} time" }
proc_block.call
# Hey Block Called time

# return after executing the whole method - Lambda
def differntiate_block(lambda_block)
puts "Inside Method"
lambda_block.call 1
puts "After Block Call"
end

lambda_block = -> (a) do puts "Hey Block Called #{a} time"
return 2
end

# Inside Method
# Hey Block Called time
# After Block Call

# return after executing Proc return statement
def differntiate_block(proc_block)
puts "Inside Method"
proc_block.call 1
puts "After Block Call"
end

proc_block = Proc.new do |a| puts "Hey Block Called #{a} time"
return 2
end

# Inside Method
# Hey Block Called time

Conclusion

Although the working of the Block, Proc, and Lambda is similar, the certain differences above make their use case more specific in their type. So be attentive to how we can use them.

--

--

Lakhveer Singh Rajput
Lakhveer Singh Rajput

Written by Lakhveer Singh Rajput

Ruby on Rails enthusiast, book lover and DevOps explorer. Follow me for insights on coding, book recommendations, and bridging development with operations.🚀📚

No responses yet