Where you and Bill agree to put off today’s job, make a roadmap, and review the basics of blocks.
You’ve barely had time to check your mail, and Bill is already making his way to your desk, eager to get to work. “I talked with the boss about today’s job,” he says. “I won’t go into the details now, but I can tell you that we’re going to need blocks for today’s project.” Before the two of you jump into the fray, you need to understand the nuances of blocks. You agree to spend the morning talking about blocks, putting off today’s project until after lunch.
On a sheet of paper, Bill lists the things he wants to cover:
A review of the basics of blocks
An overview of scopes and how you can carry variables through scopes by using blocks as closures
How you can further manipulate scopes by passing a block to instance_eval
How you can convert blocks into callable objects that you can set aside and call later, such as Procs and lambdas
You start with the first point—a quick review of the basics. (If you already know the basics of Ruby blocks, you can skip straight to .)
Do you remember how blocks work? Here is a simple example to refresh your memory:
| def a_method(a, b) |
| a + yield(a, b) |
| end |
| |
| a_method(1, 2) {|x, y| (x + y) * 3 } # => 10 |
You can define a block with either curly braces or the do…end keywords. A common convention is to use curly braces for single-line blocks and do…end for multiline blocks.
You can define a block only when you call a method. The block is passed straight into the method, and the method can call back to the block with the yield keyword.
Optionally, a block can have arguments, like x and y in the previous example. When you yield to the block, you can provide values for its arguments, just like you do when you call a method. Also, like a method, a block returns the result of the last line of code it evaluates.
Within a method, you can ask Ruby whether the current call includes a block. You can do that with the Kernel#block_given? method:
| def a_method |
| return yield if block_given? |
| 'no block' |
| end |
| |
| a_method # => "no block" |
| a_method { "here's a block!" } # => "here's a block!" |
If you use yield when block_given? is false, you’ll get a runtime error.
Now you can apply what you know about blocks to a real-life scenario.