Ruby-on-Rails
  Home arrow Ruby-on-Rails arrow Code Blocks and Iteration
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
RUBY-ON-RAILS

Code Blocks and Iteration
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 4
    2007-03-01

    Table of Contents:
  • Code Blocks and Iteration
  • 7.1 Creating and Invoking a Block
  • 7.2 Writing a Method That Accepts a Block
  • 7.3 Binding a Block Argument to a Variable

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Code Blocks and Iteration


    (Page 1 of 4 )

    Code blocks can be very confusing to newcomers to Ruby, despite the fact that many computer languages have something that functions in a similar manner. This article, the first of three parts, introduces you to code blocks. It is excerpted from chapter eight of the Ruby Cookbook, written by Lucas Carlson and Leonard Richardson (O'Reilly, 2006; ISBN: 0596523696). Copyright © 2006 O'Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O'Reilly Media.

    In Ruby, a code block (or just “block”) is an object that contains some Ruby code, and the context neccesary to execute it. Code blocks are the most visually distinctive aspect of Ruby, and also one of the most confusing to newcomers from other languages. Essentially, a Ruby code block is a method that has no name.

    Most other languages have something like a Ruby code block: C’s function pointers, C++’s function objects, Python’s lambdas and list comprehensions, Perl’s anonymous functions, Java’s anonymous inner classes. These features live mostly in the corners of those languages, shunned by novice programmers. Ruby can’t be written without code blocks. Of the major languages, only Lisp is more block-oriented.

    Unlike most other languages, Ruby makes code blocks easy to create and imposes few restrictions on them. In every other chapter of this book, you’ll see blocks passed into methods like it’s no big deal (which it isn’t):

      [1,2,3].each { |i| puts i}
      # 1
      # 2
      # 3

    In this chapter, we’ll show you how to write that kind of method, the kinds of method that are useful to write that way, and when and how to treat blocks as first-class objects.

    Ruby provides two syntaxes for creating code blocks. When the entire block will fit on one line, it’s most readable when enclosed in curly braces:

      [1,2,3].each { |i| puts i }
      # 1
      # 2
      # 3

    When the block is longer than one line, it’s more readable to begin it with thedokeyword and end it with theendkeyword:

      [1,2,3].each do |i|
        if i % 2 == 0
          puts "#{i} is even."
        else
          puts "#{i} is odd."
       
    end
      end
      # 1 is odd.
      # 2 is even.
      # 3 is odd.

    Some people use the bracket syntax when they’re interested in the return value of the block, and thedo...endsyntax when they’re interested in the block’s side effects.

    Keep in mind that the bracket syntax has a higher precedence than thedo..endsyntax. Consider the following two snippets of code:

      1.upto 3 do |x|
       
    putsx
      end
      # 1
      # 2
      # 3

      1.upto 3 { |x| puts x }
      # SyntaxError: compile error

    In the second example, the code block binds to the number 3, not to the function call1.upto 3. A standalone variable can’t take a code block, so you get a compile error. When in doubt, use parentheses.

      1.upto(3) { |x| puts x }
      # 1
      # 2
      # 3

    Usually the code blocks passed into methods are anonymous objects, created on the spot. But you can instantiate a code block as aProcobject by callinglambda. See Recipe 7.1 for more details.

      hello = lambda { "Hello"}
      hello.call
      # => "Hello"

      log = lambda { |str| puts "[LOG] #{str}" }
      log.call("A test log message.")
      # [LOG] A test log message.

    Like any method, a block can accept arguments. A block’s arguments are defined in a comma-separated list at the beginning of the block, enclosed in pipe characters:

      {1=>2, 2=>4}.each { |k,v| puts "Key #{k}, value #{v}" }
      # Key 1, value 2
      # Key 2, value 4

    Arguments to blocks look almost like arguments to methods, but there are a few restrictions: you can’t set default values for block arguments, you can’t expand hashes or arrays inline, and a block cannot itself take a block argument.*

    SinceProcobjects are created like other objects, you can create factory methods whose return values are customized pieces of executable Ruby code. Here’s a simple factory method for code blocks that do multiplication:

      def times_n(n)
       
    lambda { |x| x * n }
      end

    The following code uses the factory to create and use two customized methods:

      times_ten = times_n(10)
     
    times_ten.call(5)           # => 50
      times_ten.call(1.25)        # => 12.5

      circumference = times_n(2*Math::PI)
      circumference.call(10)  #
    => 62.8318530717959
      circumference.call(3)       #
    => 18.8495559215388
      [1, 2, 3].collect(&circumference)
     
    # => [6.28318530717959, 12.5663706143592, 18.8495559215388]

    You may have heard people talking about Ruby’s “closures.” What is a closure, and how is it different from a block? In Ruby, there is no difference between closures and blocks. Every Ruby block is also a closure.†

    So what makes a Ruby block a closure? Basically, a Ruby block carries around the context in which it was defined. A block can reference the variables that were in scope when it was defined, even if those variables later go out of scope. Here’s a simple example; see Recipe 7.4 for more.

      ceiling = 50
      # Which of these numbers are less than the target?
      [1, 10, 49, 50.1, 200].select { |x| x < ceiling }
      # => [1, 10, 49]

    The variableceilingis within scope when the block is defined, but it goes out of scope when the flow of execution enters theselectmethod. Nonetheless, the block can accessceilingfrom withinselect, because it carries its context around with it. That’s what makes it a closure.

    We suspect that a lot of people who say “closures” when talking about Ruby blocks just do it to sound smart. Since we’ve already ruined any chance we might have had at sounding smart, we’ve decided refer to Ruby closures as just plain “blocks” throughout this book. The only exceptions are in the rare places where we must discuss the context that makes Ruby’s code blocks real closures, rather than “dumb” blocks.

    More Ruby-on-Rails Articles
    More By O'Reilly Media


       · This article is an excerpt from the book "Ruby Cookbook," published by O'Reilly. We...
     

    Buy this book now. 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.

    RUBY-ON-RAILS ARTICLES

    - Iterating and Incrementing Strings in Ruby
    - Comparing and Manipulating Strings in Ruby
    - Strings in Ruby
    - Ruby On Rails: Making Your First Dynamic Site
    - Ruby on Rails: Beginning Rails
    - Ruby: Modules, Mixins, Fixins, and Rails
    - Controlling Information Access with the Rail...
    - URLs, Filters and the Rails Action Controller
    - Flash and the Rails Action Controller
    - Rails Action Controller
    - Dropping and Sorting with AJAX and script.ac...
    - Drag and Drop with script.aculo.us and Rails
    - Introducing script.aculo.us
    - Ruby Classes and Objects
    - Ruby Loops







    © 2003-2009 by Developer Shed. All rights reserved. DS Cluster 3 hosted by Hostway
    Stay green...Green IT