Home > Articles > Software Development & Management

  • Print
  • + Share This
This chapter is from the book

This chapter is from the book

Internal Iterators

Internal Iterators

If you think about it, the purpose of an iterator is to introduce your code to each sub-object of an aggregate object. Traditional external iterators do so by providing a long grappling hook, the iterator object, that you can use to pull the sub-objects out of the aggregate without getting messily involved in the aggregate details. But by using a code block, you can pass your logic down into the aggregate. The aggregate can then call your code block for each of its sub-objects. Because all of the iterating action occurs inside the aggregate object, the code block-based iterators are called internal iterators.

Building an internal iterator for arrays is very easy—we just define a method that calls (via yield) the passed-in code block for each element:1

def for_each_element(array)
  i = 0
  while i < array.length
    i += 1

To use our internal iterator, we hang a code block on the end of the method call:

a = [10, 20, 30]
for_each_element(a) {|element| puts("The element is #{element}")}

It turns out that we don’t really need for_each_element—the Array class sports a fine iterator method call called each. Just like our for_each_element method, each takes a one-parameter code block and calls that code block for each element in the array:

a.each {|element| puts("The element is #{element}")}

Run either version of the preceding code and you will get this output:

The element is 10
The element is 20
The element is 30

The each method is the explanation for all of those funny-looking each loops that you have been seeing in this book. Those loops are not, in fact, actual “built-into-the-language” loops, but rather applications of internal iterators.

  • + Share This
  • 🔖 Save To Your Account