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 ...
Get The Ruby Programming Language now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.