Block, Proc & Lambda in Ruby
A look into what are these, their differences, and their uses.
Table of Content
↦ Block
↪ yield & block_given?
↦ Proc
↪ Non-lambda
↪ Currying
↪ 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.
They’re declared in 2 ways:
1. do
…end
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.
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 likeeach
andmap
we use&
beforeProc
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:
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…
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
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:
Arguments
- 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:
- On
.call
, it doesn’t check the number of arguments. It can take more or lessarguments
than specified at the time of initialization. It assignsnil
value to the missingarguments
and ignores unexpected ones. - Ends the program when controller hits
return
method inblock
. The explicitreturn
method doesn’t work.
Lambda:
- On
.call
, it checks the number ofarguments
passed to it, will giveArgumentError
ifarguments
passed are more or less than expected. - The controller doesn’t end the program on explicit
return
. An explicitreturn
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