Why does Ruby have blocks?

Ruby’s blocks are easily the biggest hurdle most newbies to the language have to overcome. Even for people with years of experience in other languages, the the concept of blocks is often an elusive one at first.

In my opinion, some of the difficulty in grokking blocks can be chalked up to how they are usually explained. In this article, which started out as a post on Parley, I want to explain how I think of blocks: as just a pragmatic shortcut for a pattern you’ve probably already used in other languages.

Ruby, like many languages, lets us create a little anonymous hunk of executable code that can be passed around. There are various ways to do this; for the purpose of this post, let’s pretend there’s only one: proc.

proc is handy, because it is often useful to pass behavior instead of data into methods.

For instance (to use a familiar example), when opening a file, we might pass a proc of code to be executed while the file is open. Then the file will be automatically closed when the proc is finished.

The behavior that we pass, in the form of procs, into these methods is almost always one-off code. We don’t really have any reason to assign it to a local variable. So more often, we wind up passing it like this:

If you’re more familiar with JavaScript, compare this common JS idiom, where an anonymous function is passed as an argument to a method (thanks to commenter Prasanna):

The more we use methods like this that take behavior arguments as well as data arguments, we realize something: 90% of the time, the method only takes a single behavior argument. There’s something about small methods with single responsibilities that causes them to only have one piece of behavior that needs to be specified from outside.

So we start using a convention: when a method needs to be parameterized with some behavior, we always use the last as the one that takes the “block of code”, or “block” for short.

This makes our code a lot more concise for this very common case. However, as we keep doing this, we still have some objections:

  1. We start to see that proc keyword everywhere. It starts to feel a little like noise.
  2. We realize that by passing behavior as an argument, we can almost make things that look like brand new language constructs. But not quite, because there’s always the proc , and there’s always that closing parenthesis after the end .

In fact, that closing parenthesis is a particularly strong irritant in a language that normally doesn’t require us to use parentheses at all.

What if we modified the language a bit to give us some extra support for the “one argument is a block of code” convention? We could just use a special symbol to indicate which one. And then the language could let us start the block of code right after the argument list, so we don’t have to worry about that closing parenthesis. And since we’re making this part of the language syntax, let’s get rid of the requirement for the proc keyword in this special case.

Heck, while we’re at it, let’s make a way to invoke the block of code even if it hasn’t been explicitly specified as a parameter. We’ll use yield to mean “yield control to the block of code that we assume has been passed”.

And now we have Ruby blocks. The important thing to remember is that fundamentally, they are just syntactical sugar for a very common idiom: a method, one of whose parameters is a block of code used to pass in behavior.

(If you’re an experienced Ruby programmer, you probably know that blocks have some other semantic peculiarities having to do with control flow. I don’t believe this alters the core premise, however, that blocks are essentially a shortcut.)

One last word: this is totally a plug, but if you dug this article, you might like RubyTapas, where you can level up your Ruby knowledge in two coffee-break-sized nibbles per week.