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
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
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?
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
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,
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:
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
Here is a list with key points on them:
- Blocks are anonymous chunks of code that are passed to methods
- We use
yieldto call blocks inside methods as they are anonymous
- One can check if a block has been given by calling
- 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
lambdasto encapsulate them.
Procsdo not care about arity (they use nil if argument is not present) and always return immediately
lambdasare strict about arity and always return to its calling method
- Methods can specify explicit methods to be passed as arguments by using the
- 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_procand 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!! 💃