DEV Community

Cover image for Introduction to Blocks, Procs & Lambdas in Ruby
Ankit Pariyar
Ankit Pariyar

Posted on

Introduction to Blocks, Procs & Lambdas in Ruby

Block

Blocks are a set of instructions that can be passed to a method for execution. They are enclosed in a do-end block or between curly braces {}. Blocks can take multiple arguments, and their argument names are defined between two pipe characters ||.

Here's an example of a block that we can pass to the each method:

[1, 2, 3].each { |num| puts num }
Enter fullscreen mode Exit fullscreen mode

In the above code, |num| is the argument of the block, and puts num is the instruction that will be executed on each element of the array.

Yield

Yield is a Ruby keyword that executes a block of code passed to a method. The code inside the block will run when you use the yield keyword.
Here's an example of a method that takes a block and uses the yield keyword to execute it:

def print_hello
  yield
end

print_hello { puts "Hello" }
Enter fullscreen mode Exit fullscreen mode

In this example, the yield statement will execute the code inside the block and print "Hello" to the console.

You can also pass arguments to yield:

def one_two_three
  yield 1
  yield 2
  yield 3
end

one_two_three { |number| puts number * 2 }
# 2, 4, 6
Enter fullscreen mode Exit fullscreen mode

Here, we are passing the numbers 1, 2, and 3 to the block and printing their multiples of 2 to the console.

Implicit vs Explicit Blocks

There are two ways to define a block in Ruby: implicit and explicit. An implicit block is not given a name in the parameter list. It is called using the yield keyword. On the other hand, an explicit block is given a name in the parameter list.
Here's an example of an explicit block:

def explicit_block(&block)
  block.call # same as yield
end

explicit_block { puts "Explicit block called" }
Enter fullscreen mode Exit fullscreen mode

In the above example, the &block parameter is used to define the block's name. This allows us to pass the block to another method or save it into a variable to use later.

If you try to yield without a block, you will get a no block given (yield) error. To check if a block has been passed in, you can use the block_given? method.

Lambda

A lambda is a way to define a block and its parameters using a special syntax. A lambda can take arguments, and it won't run the code inside it until you call it using the call method.

Here's an example of a lambda:

hello_world = -> { puts "Hello world" }
hello_world.call

# "Hello World"
Enter fullscreen mode Exit fullscreen mode

Lambdas can also take arguments, just like methods:

times_two = ->(x) { x * 2 }
times_two.call(10)
# 20
Enter fullscreen mode Exit fullscreen mode

If you pass the wrong number of arguments to a lambda, it will raise an exception, just like a regular method.

Lambdas vs Procs

Procs are a very similar concept to lambdas, but with a few key differences. One of the differences is how you create them:

my_proc = Proc.new { |x| puts x }
Enter fullscreen mode Exit fullscreen mode

A proc behaves differently than a lambda, especially when it comes to arguments. A proc will not raise an exception if you pass the wrong number of arguments to it:

my_proc.call(1, 2, 3) # prints 1

Enter fullscreen mode Exit fullscreen mode

In this example, the proc only takes one argument, but we passed in three. The extra arguments are ignored.

Another difference between procs and lambdas is how they react to a return statement. A lambda will return normally, like a regular method. But a proc will try to return from the current context:

def test_proc
  my_proc = Proc.new { return "returning from proc" }
  my_proc.call
  return "returning from method"
end

def test_lambda
  my_lambda = -> { return "returning from lambda" }
  my_lambda.call
  return "returning from method"
end

puts test_proc # prints "returning from proc"
puts test_lambda # prints "returning from method"
Enter fullscreen mode Exit fullscreen mode

In this example, the test_proc method returns from the proc instead of continuing to execute the method. The test_lambdamethod, on the other hand, returns normally because the lambda behaves like a regular method.

Top comments (0)