: 
http://rubylearning.com/ http://rubylearning.com/satishtalim/tutorial.html http://rubylearning.com/download/downloads.html http://rubylearning.com/other/certification.html http://rubylearning.com/blog/ http://rubylearning.com/other/ruby_news.html http://rubylearning.com/other/testimonials.html http://rubylearning.com/jobs/ruby_jobs.html http://rubylearning.com/other/ruby_gurus.html http://rubylearning.com/satishtalim/services.html http://rubylearning.com/contact/contact.html http://rubylearning.com/satishtalim/about.html


Blocks and Procs

Ruby Code blocks (called closures in other languages) are definitely one of the coolest features of Ruby and are chunks of code between braces or between do- end that you can associate with method invocations, almost as if they were parameters. A Ruby block is a way of grouping statements, and may appear only in the source adjacent to a method call; the block is written starting on the same line as the method call's last parameter (or the closing parenthesis of the parameter list). The code in the block is not executed at the time it is encountered. Instead, Ruby remembers the context in which the block appears (the local variables, the current object, and so on) and then enters the method.


The Ruby standard is to use braces for single-line blocks and do- end for multi-line blocks. Keep in mind that the braces syntax has a higher precedence than the do..end syntax.


Matz says that any method can be called with a block as an implicit argument. Inside the method, you can call the block using the yield keyword with a value.


Once you have created a block, you can associate it with a call to a method. Usually the code blocks passed into methods are anonymous objects, created on the spot. For example, in the following code, the block containing puts "Hello" is associated with the call to a method greet.

greet {puts 'Hello'}

 

If the method has parameters, they appear before the block.

verbose_greet("PuneRuby") {puts 'Hello'}

 

A method can then invoke an associated block one or more time using the Ruby yield statement.

Program p022codeblock.rb i
llustrates what we have just discussed.

def call_block

  puts 'Start of method'

  yield

  yield

  puts 'End of method'

end

call_block {puts 'In the block'}


The output is:

>ruby codeblock.rb

Start of method

In the block

In the block

End of method

>Exit code: 0


If you provide a code block when you call a method, then inside the method, you can yield control to that code block - suspend execution of the method; execute the code in the block; and return control to the method body, right after the call to yield.


You can provide parameters to the call to yield: these will be passed to the block. Within the block, you list the names of the arguments to receive the parameters between vertical bars (|).


The program p023codeblock2.rb illustrates the same.


def call_block

  yield('hello', 99)

end

call_block {|str, num| puts str + ' ' + num.to_s}

The output is:

>ruby codeblock2.rb

hello 99

>Exit code: 0

Note that the code in the block is not executed at the time it is encountered by the Ruby interpreter. Instead, Ruby remembers the context in which the block appears and then enters the method.


A code block's return value (like that of a method) is the value of the last expression evaluated in the code block. This return value is made available inside the method; it comes through as the return value of yield.

 

Blocks are not objects, but they can be converted into objects of class Proc. This can be done by calling the lambda method of the module Kernel. 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.

prc = lambda {"hello"}

 

Proc objects are blocks of code that have been bound to a set of local variables. The class Proc has a method call that invokes the block. The program p024proccall.rb illustrates this.

prc = lambda {puts 'Hello'}

prc.call

 

# another example

toast = lambda do

  puts 'Cheers'

end

toast.call

The output is:

>ruby proccall.rb

Hello

Cheers

>Exit code: 0


Remember you cannot pass methods into other methods (but you can pass procs into methods), and methods cannot return other methods (but they can return procs).

 

The next example shows how methods can take procs. Example p025mtdproc.rb

def some_mtd some_proc

  puts 'Start of mtd'

  some_proc.call

  puts 'End of mtd'

end

say = lambda do

  puts 'Hello'

end

some_mtd say


The output is:

>ruby mtdproc.rb

Start of mtd

Hello

End of mtd

>Exit code: 0


Here's another example of passing arguments using lambda.


aBlock = lambda { |x| puts x }

aBlock.call 'Hello World!'

# output is: Hello World!



Learning Ruby Navigation                                                                                <Ranges  | TOC  |  Random Numbers>