Sophie

Sophie

distrib > CentOS > 5 > x86_64 > by-pkgid > 6d36cb72372cfb7c8fee63f4d6dc0530 > files > 147

ruby-docs-1.8.5-31.el5_9.x86_64.rpm

<html>
<head>
<title>Ruby FAQ: 
Iterators
</title>
</head>
<body>
<a href="rubyfaq-2.html">Previous</a>
<a href="rubyfaq-4.html">Next</a>
<a href="rubyfaq.html#toc3">Table of contents</a>
<hr>
<h2><a name="s3">3. 
Iterators
</a></h2>

<h2><a name="ss3.1">3.1 
What is an iterator?
</a></h2>


Those methods which utilize a block or a Proc
object are called iterators.
<br><br>
Iterators are used for abstraction of control
structures especially loops.
<br><br>
Let's look at an example to see what it is. Iterators are often
used to repeat the same action on each element of a collection,
like this:

<blockquote><code><pre>
data = [1, 2, 3]
data.each do |i|
  print i, &quot;\n&quot;
end
</pre></code></blockquote>

This script yields this output.

<blockquote><code><pre>
$ ruby test.rb
1
2
3
</pre></code></blockquote>

That is, the block between <code>do</code> and <code>end</code> is repeatedly executed
on each element of an array &quot;data&quot;.
<br><br>
Writing in C gives this code.

<blockquote><code><pre>
int data[3] = {1, 2, 3};
int i;
for (i = 0; i &lt; 3; i++) {
  printf(&quot;%d\n&quot;, data[i]);
}
</pre></code></blockquote>

You must be very careful on the boundary condition when using &quot;for&quot;.
You are free from such bugs with an iterator.
<br><br>
In place of <code>do</code>...<code>end</code>, you can use <code>{</code>...<code>}</code>.

<blockquote><code><pre>
data = [1, 2, 3]
data.each { |i|
  print i, &quot;\n&quot;
}
</pre></code></blockquote>

This code has the same meaning as the last example.  In some cases
<code>do</code>...<code>end</code> and <code>{</code>...<code>}</code> act differently.


<blockquote><code><pre>
foobar a, b do .. end # foobar is the iterator.
foobar a, b { .. }    # b is the iterator.
</pre></code></blockquote>
This is because <code>{ }</code> attaches stronger to the preceding expression
than a <code>do</code> block.

<h2><a name="ss3.2">3.2 
How can I pass a block to an iterator?
</a></h2>


Other than to place a block after an iterator, you can pass a Proc
object by prepending &amp; to the variable or constant that refer
the Proc object. 

<h2><a name="ss3.3">3.3 
How is a block used in an iterator?
</a></h2>


There are three ways to execute a block from an iterator method, namely,
<code>yield</code> control structure, a block argument, and <code>Proc.new</code>.
( <code>rb_yield</code> is used in C extension library.)
<br><br>
The <code>yield</code> statement may have arguments which are passed to the
block as block parameters and the block is executed.
<br><br>
A block argument appears as the last formal argument with &amp; prepended
in the iterator method arguments list.  The block is called by 
<code>method.call(args...)</code> form.
<br><br>
<code>Proc.new</code>, when used in an iterator definition, takes the block which
is given to the method as
its argument, generates a procedure object generated from the block.  The
same applies to <code>proc</code> and <code>lambda</code>.

<blockquote><code><pre>
def a (&amp;b)
  yield
  b.call
  Proc.new.call
  proc.call
  lambda.call
end
a{print &quot;test\n&quot;}
</pre></code></blockquote>
<h2><a name="ss3.4">3.4 
What does <code>Proc.new</code> without a block do?
</a></h2>


<code>Proc.new</code> without a block cannot generate a procedure object and an
error occurs.  In a method definition, <code>Proc.new</code> without a block
implies the existence of a block given by the method call.


<hr>
<a href="rubyfaq-2.html">Previous</a>
<a href="rubyfaq-4.html">Next</a>
<a href="rubyfaq.html#toc3">Table of contents</a>
</body>
<html>