ruby_cool_kid.rb — Blocks, Proc, and Lambdas the close siblings. Part 3

Pablo Adell
4 min readFeb 26, 2022

--

Photo by Joshua Fuller on Unsplash

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 and lambdas to encapsulate them.
  • Procs do not care about arity (they use nil if argument is not present) and always return immediately
  • lambdas 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.

--

--

Pablo Adell
Pablo Adell

Written by Pablo Adell

Hello there!! My name is Pablo, I am a Full-Stack Software Engineer at Affirm, focused mainly in Ruby on Rails and React. I hope you enjoy my content!