After learning a bit about Ruby and the basic way that data is stored and manipulated I came across the concept of the Block.
I was enthralled…and bewildered.
The concept seemed simple enough. Blocks are pieces of code, or instructions, that are passed to a function.
Amazing! Passing messages to other messages! This sounds highly advanced. I confess my first thought “Why would I ever want to pass a message to another message”?
This blog entry will begin with the syntax used to pass a Block to a function and finish with a discussion on the usefulness of being able to pass code to a function.
So first a bit about Blocks in general. A Block is a bit of code that follows a
function call and is contained within a set of braces
delimiters. There is a common convention that braces should be used where the
Block is only one line and
end delimiters are used where the code
extends over multiple lines. Examples below…
1 2 3 4 5
_Jim Weirich discusses another convention specific to the presence of a return value in his blog entry.
Regardless of how the Block is defined, it is always listed after a message starting on the same line as the message call.
1 2 3 4 5
1 2 3
1 2 3 4
1 2 3
The second example demonstrates how a Block can accept an argument passed to it from the function. In this case it is the subject or value of the array.
So a block is a piece of logic that is passed with a message. But other than utilizing simple pre-built iterators how can I unleash a Block within my own code? How can I write a function that accepts a Block?
Blocks are implicitly accepted by all functions. Even if the function does not use the block, it is valid syntax to pass it.
However, often, you do want to use the block. To write the function to
accommodate the presence of the block use
yield. To provide a default
behavior if no block is provided it can be switched on with
When the function reaches
yield the block is invoked. If arguments are to be
passed to the block they are listed after
1 2 3 4 5 6 7 8 9
Blocks are particulary usefull when you find yourself writing lots of functions
containing the same code. If you have five functions with code that differs
only by one line…consider using a block. This way, you can condense all of
the functions into one well written function that contains a
with the differing code.
Another similar example would be writing a function that contains a bit of
logic that might change in the future (think
each). If you build a function
that iterates through an array and performs a bit of logic on each index you
could write a function that accepts a block containing the logic to perform.
The following example shows code that might exist for a program designed to
automate yard maintenance. The
Yard function has a public interface called
maintain_garden that contains several functions needed for garden upkeep.
1 2 3 4 5 6 7 8 9
Utilizing a block the
maintain_garden function is dynamically able to provide
a way for others to hook in additional behavior. This way, if we decide to add
harvest_garden we can pass them into
the function without having to modify the default behavior.
1 2 3 4 5 6 7 8 9 10 11 12 13
Block’s can be used to make your functions more versatile allowing you to reduce duplication of code (making your code more DRY). They can also be utilized where logic may change in the future. Instead of having to go back and manipulate the code within a function a block can be used to pass new logic to the existing function.