This post is part of a series of reviews on the book Design Patterns in Ruby. Check out the Introduction post for a full table of contents along with some generic principles regarding Design Patterns.
An Iterator is simply an object that provides a way to access the elements of a certain collection. If this iteration happens inside or outsite the collection, it depends on how you implement it. Since we’re gonna go deeper in internal iterators, let’s take a quick look at external iterators, which are objects that sweep you through a collection without knowing it’s insides:
class ArrayIterator def initialize(array) @array = array @index = 0 end def has_next? @index < @array.length end def item @array[@index] end def next_item value = @array[@index] @index += 1 value end end
Using this code is dead simple, and due to Ruby’s dynamic typing we can use it on any object that has a length and a  method, such as String:
#Array i = ArrayIterator.new(['a', 'b','c']) while i.has_next? puts i.next_item end #String i2 = ArrayIterator.new('abc') while i2.has_next? puts i2.next_item end
It works and it doesn’t look like much to do, but let’s see how internal iterators are just way simpler. Internal iterators in Ruby work with blocks, you simply call an iterator method and pass it a block of code to execute at each member of the collection, and so the method will simply yield at each one. Let’s see how that works.
def for_each(array) i = 0 while i < array.length yield(array[i]) i+=1 end end a = [1,2,3] for_each(a) do |element| puts element end
The thing is, you don’t build yourself internal iterators, you could, but why reinvent the wheel? Ruby ships with a powerful module called Enumerable which gives you a bunch of handy iterators, and all you need to do is include the module and define the basic iterator for it (each). Say you have a Tree and would like to iterate through its branches:
class Tree include Enumerable def initialize @branches =  end def each(&block) @branches.each(&block) end def <<(branch) @branches << branch end end tree = Tree.new tree << 'branch1' tree << 'branch2' tree << 'branch3' tree.each do |branch| puts branch end
Of course that in most cases you do want to use an internal iterator since it’s so much simpler in terms of code, but knowing about external iterators can be interesting when things get dirty.
For instance, an advantage of using external iterators is that since you’re using someone else to sweep an object for you, changing the object won’t screw everything up because we’re only iterating case the next object in line is good to go, where in internal iterators you just force yourself through the next block without a single care.