0.1 Yield

Yielding to Blocks

As you use blocks, you will discover that the most common usage involves passing exactly one block to a method. This pattern is extremely popular in the Ruby world, and you'll find yourself using it all the time.

Ruby has a special keyword and syntax to make this pattern easier to use, and yes, faster! Meet the yield keyword, Ruby's implementation of the most common way of using blocks.

Here's an example that uses regular block syntax.

Example Code:

Output Window

As you can see, the calculation method accepts two numbers and a block that can perform a mathematical operation.

Let's now do this using yield:

Example Code:

Output Window

As you can see, the results are identical. Feel free to play around with the example to get a better feel for the new syntax.

Let me call out how the example using yield is different from the regular approach.

  • The block is now no longer a parameter to the method. The block has been implicitly passed to the method - note how it's outside the parentheses.
  • Yield makes executing the block feel like a method invocation within the method invocation rather than a block that's being explicitly called using Proc#call.
  • You have no handle to the block object anymore - yield "magically" invokes it without any object references being involved.

Note that blocks can be passed implicitly to methods without any parameters. The syntax remains the same.

Here's an example where neither the method nor the block take any parameters.

Example Code:

Output Window

Magic Blocks

I call yield "magical" because every object oriented rule in Ruby is suspended for this special mode of block invocation.

Let's see what rules are bent, and what broken.

1) Yield is not a method

Example Code:

Output Window

As you can see, the program blows up with an exception on the last line in the method. Clearly yield calls the block, the method method correctly returns the object that represents foo as expected, but then blows up on yield. So yield isn't really a method even though it looks like one (turns out, it's a keyword).

2) Objects are abandoned

Everything in Ruby is an object. Now where's the object that represents the block? How is yield getting access to it and seemingly invoking the call method on it?

We don't know. As programmers using the language, all we can tell is that the normal rules have been suspended.

We’ll see exactly why all these rules are broken later in this lesson.

Is it a given?

With implicit blocks, it's hard to be sure if a block has actually passed. Doing a yield when there's no block can have unfortunate consequences - an exception (a LocalJumpError) with the message "no block given" is raised .

Example Code:

Output Window

To defend against this outcome, Ruby offers the block_given? method that tells you if a block has been passed to a method implicitly. Make the call to yield conditional on this method returning true and you'll be fine.

Output Window

Faster, Faster!

I have already mentioned that using yield speeds up your code. Let us see how, through the following example.

Example Code:

Output Window

So here we have the evidence: Breaking all those object oriented programming rules buys us a bunch of speed.

Practice makes perfect

The best exercises are those that are self-explanatory. This is one such. Your goal is to make all the tests pass.

Congratulations, guest!


% of the book completed

or

This lesson is Copyright © 2011-2014 by Jasim A Basheer