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.