20
Understanding Blocks & Procs in Ruby
Blocks in Ruby are fairly easy to understand. A block simply contains chunks of code inside and can be passed into methods. If you're familiar with javascript, then a block is equivalent to an anonymous function.
Blocks can be created in two ways, using {..}
or the do..end
syntax.
{..}
is used for single line blocks, while do..end
syntax is used to encapsulate multiple lines of code.
Unlike methods, you should never use the return
keyword inside a block unless you have a really good reason for it. Lets explore why..
You see, the return
keyword always belong to methods, so in the second example when words.map
iterates over the array, it instantly returns the first word it encounters and yell_words
ends immediately with the output of "LION!" which is not at all what we were expecting. This is a common pitfall for programming newbies, and I surely have been a victim numerous times.
The last thing I want to point out is a shorthand for writing methods that only take 'one' argument that calls a single method. Lets take a peek:
Lets break this down to understand what all of it means. First, we are calling Array.select
and passing in the argument &:odd?
. The :odd?
part is just a symbol that refers to the Integer#odd?
'method', which will be called on every element of the array, and &
is used to convert the 'method' into a Proc(a normal Ruby object) that can be passed into select
.
In Ruby it's not possible to pass methods into other methods so we must convert them to Procs in order to do that.
A proc is a ruby object that contains a block inside. Through procs, we are able to pass blocks of code around or even save them to a variable. See example below:
Now lets see how we can pass a proc into other methods:
Notice that we can really alter the behavior of methods by passing in procs that do different things depending on our needs. That's great and all, but can we shorten this a bit? Yes we can!
Ruby allow us to automatically convert blocks into procs. Remember our old friend &
from the block's example, earlier? Lets see how it works:
It's important to note that since we added &prc
as the third argument of the method, combine_and_proc
must always be called with a block or it will throw an error. The block will be taken by the &prc
argument, and &
will turn the block into a proc. Now when we call puts prc.call(word)
inside combine_and_proc
there will be no errors because prc
was turned into a proc by Ruby automatically.
To wrap up, i'd like to mention one last thing that our friend &
can do for us, and that is to turn a proc into a block. Yes, it might sound confusing but it works both ways. Lets take a look:
From the previous example we can gather that select
takes in a block as its last argument. Then, we created the proc odds
and passed it like this [1,2,3].select(odds)
and so we get an error because odds
is a proc and select
is expecting a block. So the correct way would be to call select with &odds)
because &
will turn the proc into a block right before giving it to the select
method.
I hope these examples were helpful, and please feel free to alert me of any corrections to the article.
Happy coding 😃
20