Code Blocks and Iteration - 7.1 Creating and Invoking a Block
(Page 2 of 4 )
Problem
You want to put some Ruby code into an object so you can pass it around and call it later.
Solution By this time, you should familiar with a block as some Ruby code enclosed in curly brackets. You might think it possible to define a block object as follows:
aBlock = { |x| puts x } # WRONG
# SyntaxError: compile error
That doesn’t work because a block is only valid Ruby syntax when it’s an argument to a method call. There are several equivalent methods that take a block and return it as an object. The most favored method isKernel#lambda:*
aBlock = lambda { |x| puts x } # RIGHT
To call the block, use thecallmethod:
aBlock.call "Hello World!"
# Hello World!
Discussion The ability to assign a bit of Ruby code to a variable is very powerful. It lets you write general frameworks and plug in specific pieces of code at the crucial points.
As you’ll find out in Recipe 7.2, you can accept a block as an argument to a method by prepending&to the argument name. This way, you can write your own trivial version of thelambdamethod:
def my_lambda(&aBlock)
aBlock
end
b = my_lambda { puts "Hello World My Way!" }
b.call
# Hello World My Way!
A newly defined block is actually aProcobject.
b.class # => Proc
You can also initialize blocks with theProcconstructor or the methodKernel#proc. The methodsKernel#lambda,Kernel#proc, andProc.newall do basically the same thing. These three lines of code are nearly equivalent:
aBlock = Proc.new { |x| puts x }
aBlock = proc { |x| puts x }
aBlock = lambda { |x| puts x }
What’s the difference?Kernel#lambdais the preferred way of creating block objects, because it gives you block objects that act more like Ruby methods. Consider what happens when you call a block with the wrong number of arguments:
add_lambda = lambda { |x,y| x + y }
add_lambda.call(4)
# ArgumentError: wrong number of arguments (1 for 2)
add_lambda.call(4,5,6)
# ArgumentError: wrong number of arguments (3 for 2)
A block created withlambdaacts like a Ruby method. If you don’t specify the right number of arguments, you can’t call the block. But a block created withProc.newacts like the anonymous code block you pass into a method likeEnumerable#each:
add_procnew = Proc.new { |x,y| x + y }
add_procnew.call(4)
# TypeError: nil can't be coerced into Fixnum
add_procnew.call(4,5,6) # => 9
If you don’t specify enough arguments when you call the block, the rest of the arguments are givennil. If you specify too many arguments, the extra arguments are ignored. Unless you want this kind of behavior, uselambda.
In Ruby 1.8,Kernel#procacts likeKernel#lambda. In Ruby 1.9,Kernel#procacts likeProc.new, as better befits its name.
See Also - Recipe 7.2, “Writing a Method That Accepts a Block”
- Recipe 10.4, “Getting a Reference to a Method”
Next: 7.2 Writing a Method That Accepts a Block >>
More Ruby-on-Rails Articles
More By O'Reilly Media
|
This article is excerpted from chapter seven of the Ruby Cookbook, written by Lucas Carlson and Leonard Richardson (O'Reilly, 2006; ISBN: 0596523696). Check it out today at your favorite bookstore. Buy this book now.
|
|