Great news! Ruby has several ways of creating and passing around anonymous functions. Key language features like the Enumerable
module would not be possible without this capability.
You might not even realize that when you are using a function that takes a block, you have just written an anonymous function. An anonymous function is exactly what it sounds like: a function with no name.
1 2 |
|
In this example, the { |note| note.capitalize }
bit is the anonymous function. Used in this way the {}
characters are block literals, passing function expecting one variable to the higher-order map!
method.
Our own methods that take blocks
We can pretty easily write our own methods that accept blocks like this.
1 2 3 4 5 |
|
Which we can use like this
1 2 3 4 5 6 7 |
|
We use blocks expecting an argument in a very similar way.
1 2 3 4 5 6 7 8 |
|
Use yield
for a nice performance boost
There’s an alternative syntax available to us when writing methods expecting blocks: the yield
keyword. We should prefer it because benchmarking shows that yield
is about 5x faster than block.call
.
1 2 3 4 5 6 7 8 |
|
Overcoming limitations of blocks with Proc
If you do a little experimentation, you might notice that this brace syntax is a syntactic sugar that can only be used after a method call.
1 2 |
|
There’s also no way to pass multiple blocks to a single function. So a very common idiom in other langauges like JavaScript is to pass multiple functions to be used in different circumstances. For example, when making an Ajax call it’s convenient to pass both a success and error callback so our code knows how to continue in both situations:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
The equivalent ruby would be something like
1 2 3 |
|
We can’t use blocks to send success
and error
callbacks to this method. To accomplish this type of feat with Ruby, we have to use Proc
objects, which Ruby provides as a way of wrapping a block into an object that may be passed around and used in multiple places. This is useful to use because methods can accept an arbitrary number of object parameters.
The simplest possible example of a Proc
would be something like this:
1 2 |
|
Using Proc
and keeping in mind that blocks are closures, we can write functions that return Procs.
1 2 3 4 5 6 7 8 9 10 |
|
Using a proc where a block is expected
If we need to use a proc where a block is expected, we can use the &
operator.
1 2 3 |
|
Choose your own syntax
Because Ruby likes to have multiple ways to accomplish everything, we’ve got several different sytnaxes available to us for constructing Proc
objects.
1 2 3 4 5 6 7 8 9 10 11 |
|
The Proc methods and lambda methods are almost exactly the same except for the strange way the return
keyword is handled in procs created with Proc.new
.
The “stabby lambda” syntax, though probably the ugliest of all, can do something that none of the others can and that is specify default parameters similar to a normal method declaration.
1 2 |
|
Handy!
Gimme that method
One final trick to have up your sleeve it the ability to reach inside an object and turn any method into a Proc
.
1 2 3 4 5 6 7 8 9 10 11 |
|
Summary
Amazing! That concludes the tour of ruby’s blocks, procs, and lambdas.
To summarize:
- Use blocks for one-off inline anonymous functions.
- Use
Proc.new
if you need to reuse a code multiple times or need to pass multiple functions as arguments to the same function. - Use
->
if you want to specify default parameters for your anonymous function.