Block, Proc & Lambda in Ruby

Juzer Shakir
4 min readJul 1, 2021

--

A look into what are these, their differences, and their uses.

Table of Content

Block
yield & block_given?

Proc
Non-lambda
Currying
Lambda

Proc vs Lambda

What is a Block?

A Block is an unnamed chunk of code passed that’s passed into a method. They’re also known as anonymous function because they aren’t named and behave just as functions.

Topics covered on block

They’re declared in 2 ways:
1. doend
2.
{}.
For example:

1!
2!
3!
1!
2!
3!

To begin with, we created an array and passed in an iterable method each that takes a block. As we can see, both multi-line and single-line blocks give us the same output with a difference in syntax.

yield & block_given?

Block provides 2 more methods, yield and block_given?

yield runs the block on the line where it's given and we can also set parameters to it.

If the block is given, block_given? returns a boolean value true or false.

Block Given
Yield output

At line #11, we passed block_hungry without a block which doesn’t output anything because the method block_given? outputs only for blocks.

At line #14, we passed block_hungry with a block which gives an output of 2 lines. On line #7, yield is given with parameters “Argument” even though our block doesn’t take any argument, the yield doesn’t raise an error and outputs the block as ‘Yield output’.

Now:

We called the method, passed a block with argument to it and returned this output.

Block Given
Yield can take arguments too: Argument

Proc

A Block that we save in a variable is called Proc! They come in two flavors: Lambda and Non-lambda or Proc.

So this means that instead of writing a whole block, you write it once, save it in a variable, and call that variable (Proc/lambda) whenever you want to use the block.

This will make more sense after you have read this article.

Let's look into Non-lambda or Proc first:

Output:

1
4
9
1
4
9

Block initiated with curly braces, takes an argument and squares each number, and saves this to a variable as a Proc. Now we can use this block as many times as we want by passing its name (my_proc) as an argument to a method.

To pass Proc into built-in methods like each and map we use & before Proc name.

.call for Proc

Just as we used yield method to run block at a particular line, we use .call method to a Proc and it runs its block. It takes arguments too.

One more example of it:

Making square method available to an Array class.

So if I want to square each element in the array, I call .square_it method which I defined explicitly in Array class. Inside .square_it method, it's not the method that does the squaring but a Proc which is called inside the method by .call and passed each element of an Array as an argument.

Another example where we see both block and Proc in action:

49
Block!

I think by now you have well understood this and the program is self-explanatory.

Currying

Currying is a way to set a value of an argument now and then later set the values of the remaining arguments.

There’s one more thing about Procs that needs to be discussed…

No Explicit return
Implicit return!
Implicit return!

As you can see, explicit return method at line #5 doesn’t work, because it only allows us to use implicit returns puts or p. The last puts method doesn’t execute because when it runs into explicit return method, the program exists completely.

And the second thing about Proc is that they don’t raise an ArgumentError

No ArgumentError

We called Proc without giving any argument as the method was expecting one. It didn’t raise ArgumentError and value of it is nil.

Lambda

Its implementation is little similar to Proc but its output is a little different from it. Here’s an example:

#<Proc:0x00005611cab3b3e8 lambda.rb:2 (lambda)>
1 and 2
Explicit return
#<Proc:0x00005611cab3b0a0 lambda.rb:13>
1 and

We see that block of both Proc and Lambda is the same but there are differences in 2 things:

  1. Arguments
  2. Explicit return

When we call lambda with an incorrect number of arguments it gives us ArgumentError, just as any method would. It expects the same number of arguments to be passed when lambda was initialized. Hence lambda is stricter in terms of arguments.

And as we saw in an earlier program that a Proc would exit the program when the controller would hit return, but that’s not the case for lambda. It executes the return method just fine.

Proc vs Lambda

We covered both topics of Procs or Non-lambda and Lambda, here are the key differences between them:

Procs:

  1. On .call, it doesn’t check the number of arguments. It can take more or less arguments than specified at the time of initialization. It assigns nil value to the missing arguments and ignores unexpected ones.
  2. Ends the program when controller hits return method in block. The explicit return method doesn’t work.

Lambda:

  1. On .call, it checks the number of arguments passed to it, will give ArgumentError if arguments passed are more or less than expected.
  2. The controller doesn’t end the program on explicit return. An explicit return works.

So in a nutshell, that is it about Block, Procs, and Lambda. I hope the explanation was thorough and understandable. Any tips or suggestions for improvement would be highly appreciated!

My previous article: Constants in Ruby
My next article: Strings & Symbols in Ruby

GitHub | LinkedIn

--

--