ruby_cool_kid.rb — Blocks, Proc, and Lambdas the close siblings. Part 3
In past episodes of this topic, we have spoken about Blocks(meter link) and Procs and lambdas(meter links).
However, their behavior and purpose can be extended falling into more complex topics
The &
To put the cherry on top of this saga, we will talk about &
. As it happened with yield
, if you have been coding in Ruby enough, you will have already seen it. If not, this is it 😉
Before going deep into its meaning, there is a key definition that will help us better understand it. The difference between explicit and implicit blocks.
Implicit blocks are called with yield and passed to methods, as we saw in previous examples, either by curly braces
or by the do...end statement
.
In Ruby, all methods can take implicit blocks without specifying it on the parameter list.
On the contrary, explicit blocks are specified on the argument list of a method. We are explicitly stating that we expect the method to take an optional block. In order to state this, we use &
. The &
will call to_proc
on the passed object, thus passing the block to the method.
When stating the explicit block, the argument and the variable passed, must have &
as a prefix, to indicate the explicit block. However, inside the method, we can get rid of the &
.
Passing the block as an argument could be optional, so we need a mechanism that allows us to be certain that the block exists.
We mentioned before that block_given?
could be used when using yield
for calling a block, but the same method can be used for explicit blocks when passed to a method.
What will happen if we pass an implicit and an explicit block?
However, since block_given?
does not receive any explicit argument, what will happen if we passed two blocks to the same method? Let’s see:
Ruby will raise syntax errors: both block arg and actual block given
, stating that two blocks have been passed.
Method as a block
Given the nature of a method, in Ruby we can get a reference to it, belonging to the Method
class. If we take a look to the Method
class:
It implements to_proc
, making it possible to use it as a block to another method. Let’s modify our previous example picture this:
Here you can see how we take the reference to our method by calling method
and passing the name of the method as a symbol. Then, as we know, &
calls to_proc
on the passed variable, thus allowing us to use the method as an explicit block.
Bearing this in mind, we can understand a common statement found in Ruby when iterating through an object of the Enumerable
class. Bringing back our grocery shopping list:
As map!
calls yield of the given block for each of the elements on the Enumerable
object, we can pass a reference to another method to be executed having each item as the argument of the method.
If the method was public for the item in the Enumerable
object, like it, may happen with downcase
, for Strings. We could even simplify the code as:
Here, we are calling .downcase
on every item as we are yielding its symbol.
This sums up our saga on blocks
, Procs
and lambdas
.
Here is a list with key points on them:
- Blocks are anonymous chunks of code that are passed to methods
- We use
yield
to call blocks inside methods as they are anonymous - One can check if a block has been given by calling
block_given?
- Blocks are not objects, as they are not instantiated from any class nor have inheritance chains or instance variables. They are just bound to the scope where they were defined, and cannot be stored in variables, so we use
Procs
andlambdas
to encapsulate them. Procs
do not care about arity (they use nil if argument is not present) and always return immediatelylambdas
are strict about arity and always return to its calling method- Methods can specify explicit methods to be passed as arguments by using the
&
keyword. - Implicit and explicit blocks cannot be passed at the same time to the same method
- A method can be converted to a proc by calling
to_proc
and passed to another method to be executed as an explicit block.
As usual, thank you very much for stopping by to read this article. Have a good day 😁
See you around!! 💃
Pablo.