Creating and Invoking a Block

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 is Kernel# lambda:[3]

[3] The name lambda comes from the lambda calculus (a mathematical formal system) via Lisp.

	aBlock = lambda { |x| puts x } # RIGHT

To call the block, use the call method:

	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 the lambda method:

	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 a Proc object.

	b.class # => Proc

You can also initialize blocks with the Proc constructor or the method Kernel#proc. The methods Kernel#lambda, Kernel#proc, and Proc.new all 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#lambda is 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 with lambda acts like a Ruby method. If you don't specify the right number of arguments, you can't call the block. But a block created with Proc.new acts like the anonymous code block you pass into a method like Enumerable#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 given nil. If you specify too many arguments, the extra arguments are ignored. Unless you want this kind of behavior, use lambda.

In Ruby 1.8, Kernel#proc acts like Kernel#lambda. In Ruby 1.9, Kernel#proc acts like Proc.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"


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net