Internal Iterator
External iterator classes are verbose to use and to define. You need to define an iterator class for each collection class, and you need to update them in parallel. To use it, you need to instantiate the iterator and make method calls to iterate, fetch and see if there are more.
In 99% of use cases, all you want to do is run a block of code against each element.
A fourth option, which is in the general case superior to all three of your options, is the internal iterator. It delegates management of the iteration to the collection, rather than adding repetitive boilerplate to your functional code.
An internal iterator is an instance method of a collection which is passed a function which it calls for each element in the collection.
An example of internal iterators is seen in Ruby's core collection classes.
For the technically-minded, let me demonstrate the difference between the two with code (Ruby, because it's shorter). (Download the code from http://dave.burt.id.au/ruby/pair.rb to see it indented properly.)
class Pair
attr_accessor :first, :last
def initialize(first = nil, last = nil)
@first = first
@last = last
end
# The internal iterator is an instance method
def each
yield first
yield last
end
# The external iterator is a full-blown, separate class
# which also wants an instance method to obtain an
# iterator instance
def iterator
Iterator.new(self)
end
# Wow, this iterator's definition is longer than the
# collection's!
class Iterator
def initialize(pair)
@pair = pair
@next = :first
end
def has_next?
@next.nil?
end
def next
case @next
when :first
@next = :last
first
when :last
@next = nil
last
else
fail
end
end
end
end
col = Pair.new "a", "b"
# Internal iterator: just pass the block to the iterator
col.each do |x|
print x
end
# External iterator: instantiate, check, fetch
iter = col.iterator
while iter.has_next?
x = iter.next
print x
end