views:

116

answers:

7

I started learning Ruby on Rails and found myself confounded by the syntax, so I had to read about somet of the Ruby syntax. I learned the syntax from http://www.cs.auckland.ac.nz/references/ruby/doc_bundle/Manual/man-1.4/syntax.html:

method_call do [`|' expr...`|'] expr...end

They call it an Iterator. I understand an iterator runs through a loop, but I don't understand how exactly I'm supposed to read this or what's going on in in this syntax. I see it all the time in RoR screencasts and the words make sense, but I actually have no idea what's going on. Could anyone explain this to me?

edit: example

respond_to do |format|
    format.json
    format.xml { render :xml => @posts }
end
+3  A: 

Methods can take a construct called "Blocks". These are anonymous methods that get passed into the method.

Another syntax for this is:

method_call { |var| do_something(var) }

Basically, you are saying that for each item in an iteration, name it "var" and do something with that item. The method simply calls your block that you passed in as it "yields" items to it.

Does this help?

edit: In your example, you they are using the iterator pattern in a funny way... probably only passing one format object into your block, so you can then tell it which formats to handle, and what to do when you see it.

In other words, they are using the pattern to create a DSL of sorts that lets you configure what you respond to.

Brian Genisio
Thanks, I never would have guessed it was an anonymous function. I understand the syntax now, but could you explain the DSL a bit?
Gio Borje
A DSL (Domain-specific language) is something that lets you declare information about your domain (in this case, a website) in its own language. In this case, it lets you declare what formats you respond to, in a extremely declarative way.
Brian Genisio
Ruby DSLs use this a lot: the Rails example is clearly one - also have a look at Rake and Capistrano got clear examples of Ruby DSLs.
Tom Morris
+1  A: 
<function> do |<temp variable>|
    <code to operate on temp variable>
end

This creates a temporary anonymous function which accepts an item into a temporary variable, and then lets things operate on that item. The anonymous function is passed in to the original <function> specified to operate on the items yielded by that function.

Amber
A: 

The documentation you are reading is ancient -- practically prehistoric. If it were possible for web pages to gather dust, that one would have a thick layer.

Try the reference material at the ruby-lang website. Also, the Programming Ruby (pickaxe) book is an essential reference.

zetetic
I was just looking for a guide to the syntax instead of "learn programming from scratch" guides.
Gio Borje
I understand. If you haven't already, have a look at the pickaxe book chapter titled "The Ruby Language", which has a very readable and comprehensive description of the syntax.
zetetic
+2  A: 

In the case of iterators, think of them like an interface in Java: you can do a for-loop in Ruby, but all the objects that you might want to iterate over (should) implement the 'each' method which takes a block (i.e. a closure, an anonymous function).

Blocks are used all over the place in Ruby. Imagine you have this array:

[1, 2, 3, 4, 5, 6].each do |i| puts i.to_s end

Here, you are creating the array and then you are calling the 'each' method on it. You pass the block to it. You could separate this out, like this:

arr = [1, 2, 3, 4, 5, 6]
string_printer = lambda do |i| puts i.to_s end
arr.each(&string_printer)

This kind of interface is implemented in other things: the Hash collection lets you iterate over the key-value pairs:

{:name => "Tom", :gender => :male}.each do |key, value| puts key end

The do..end can be replaced with braces, like this:

[1, 2, 3, 4, 5, 6].each {|i| puts i.to_s }

This kind of iteration is made possible because of the functional-programming that Ruby employs: if you are creating a class that needs to iterate over something, you can also implement the each method. Consider:

class AddressBook
  attr_accessor :addresses
  def each(&block)
    @addresses.each {|i| yield i }
  end
end

All sorts of classes implement interesting functionality through this block pattern: look at String's each_line and each_byte method, for instance.

Tom Morris
+2  A: 
method_call do [`|' expr...`|'] expr...end

Is not limited to iteration functions.

In ruby, any method can take a block as an argument. The block can then be called by the method. In the case of an iterator, the method looks something like this:

def iter
  for i in [:x,:y,:z]
    yield i
  end
end

If you call iter with a block, it will loop over [:x, :y, :z] and yield each of them to the block, which can then do whatever you want. e.g. to print them out:

iter { |z| puts z }

You can also use this to hide init and cleanup steps, like opening and closing files. e.g. File.open. File.open, if it were implemented in pure ruby(it's in C for performance) would do something like this.

def File.open filename, opts
  f = File.new filename, opts
  yield f
  f.close
end

Which is why you can use

File.open 'foobar', 'w' do |f|
  f.write 'awesome'
end

respond_to is similar. It works something like this:( check out the real implementation here)

   def respond_to
     responder = Responder.new(self)
     block.call(responder)
     responder.respond
   end

It creates a responder object that has methods like html that take a block and passes it to you. This turns out to be really handy, because it lets you do things like:

def action
  @foo = Foo.new params[:foo]
  respond_to do |format|
    if @foo.save
      format.html { redirect_to foo_path @foo }
      format.xml { render :xml => @foo.to_xml }
    else
      flash[:error] = "Foo could not be saved!"
      format.html { render :new }
      format.xml { render :xml => {:errors => @foo.errors }.to_xml}
    end
  end
end

See how I change the behavior dependent on save inside the block? Doing this would be much more annoying without it.

BaroqueBobcat
A: 
giraff
+1  A: 

What you see there is a block of code, the syntax is a bit awkward when you first see it.

So, basically, with iterators your have a "thing" that may be repeated, and it receives a block to know what to do.

For instance the Range class has a method called "each" which receives the block of code to execute on each element in the range.

Let's say you want to print it:

range = 1..10 #range literal 
range.each {|i|
    puts i
}

The code: {|i| puts i} is a block that says what to do when this range iterates over each one of its elements. The alternate syntax is the one you posted:

 range.each do |i|
      puts i 
 end

These blocks are used with iterators, but they are not limited to "iteration" code, you can use them in other scenarios, for instance:

class Person 
  def initialize( with_name ) 
    @name = with_name
  end
  # executes a block 
  def greet 
      yield @name #passes private attribute name to the block 
  end 
end 

p = Person.new "Oscar" 
p.greet { |n|
     puts "Name length = #{n.length}"
     puts "Hello, #{n}"
}

Prints:

Name length = 5
Hello, Oscar

So, instead of having a greet method with a fixed behavior, using block let the developer specify what to do, which is very helpful with iterators, but as you have just witness not the only place. In your case, that block is letting you specify what to do in the respond_to method.

OscarRyz