Iterators and Enumerable Objects
Although while, until, and for loops are a core part of the Ruby
language, it is probably more common to write loops using special
methods known as iterators. Iterators are one of
the most noteworthy features of Ruby, and examples such as the following
are common in introductory Ruby tutorials:
3.times { puts "thank you!" } # Express gratitude three times
data.each {|x| puts x } # Print each element x of data
[1,2,3].map {|x| x*x } # Compute squares of array elements
factorial = 1 # Compute the factorial of n
2.upto(n) {|x| factorial *= x }
The times, each, map,
and upto methods are all iterators, and they interact with the
block of code that follows them. The complex
control structure behind this is yield. The yield statement temporarily returns control
from the iterator method to the method that invoked the iterator.
Specifically, control flow goes from the iterator to the block of code
associated with the invocation of the iterator. When the end of the
block is reached, the iterator method regains control and execution
resumes at the first statement following the yield. In order to implement some kind of
looping construct, an iterator method will typically invoke the yield statement multiple times. Figure 5-1 illustrates
this complex flow of control. Blocks and yield are described in detail in Blocks below; for now, we focus on the iteration itself
rather than the control structure that enables it.
Figure 5-1. An iterator yielding to its invoking ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access