InternalIterator''''''s are convenient. They take up very little space, they reveal the intention of the code and they provide a mechanism for localizing and reusing the code that lives in their function parameters. They are also inflexible, however. They cannot iterate over more than one collection at a time, they cannot be paused or stopped in the middle and they can only implement a single traversal strategy. ExternalIterator''''''s, on the other hand, ''can'' do all of these things. Unfortunately, they are dumb, they must be told every step to be taken even though they are almost always told to do the exact same thing. What we would like is the ability to easily and compactly express our intention the way we can with InternalIterator''''''s while still having the degree of control provided by ExternalIterator''''''s. '''Therefore:''' InternalizeExternalIterators by using ExternalIterator''''''s to implement InternalIterator''''''s. Collections implement a set of standard InternalIterator''''''s that allow most normal traversals: forward, reverse, MapFunction, FoldFunction, etc. But they also provide ExternalIterator''''''s that allow more exotic iterations to be implemented. These algorithms are implemented as InternalIterator''''''s so that they can be used just like the standard InternalIterator''''''s. They can be implemented as member functions in a class derived from the collection (in which case the ExternalIterator''''''s can have "protected" access), as free functions, as GenericFunction''''''s that implement ExternalPolymorphism, or as traits (http://www.iam.unibe.ch/~scg/Research/Traits/). ''Does this have anything to do with TraitsTemplates?'' See also: TransfoldPattern, TellDontAsk, BlocksInJava ---- DylanLanguage has this pattern. Collections provide methods for forward-iteration-protocol, reverse-iteration-protocol, and, if appropriate, table-protocol. These return a group of functions that provided the normal iterator functionality - initial-state, next-state, finished-state?, current-element, and current-element-setter. Algorithms can use these to iterate through the collection, but rarely do. Instead, they use the InternalIterator''''''s defined in terms of these iteration protocols. Dylan provides methods for do, map (& map-into, map-as, etc.), reduce, choose, etc. Most programs use these instead of the internal iterators for most collection operators. ---- If your language supports coroutines, light-weight processes, continuations, or other such beasts, you can also externalize an InternalIterator. In such cases, the '''Therefore:''' equals '''Maybe, depending on other tradeoffs:''' ---- Here's how you can externalize an internal iterator in Scheme: (define (externalize iterator) (letrec ((iterator-return #f) (produce-next-value (lambda (dummy) (iterator (lambda (value) (call-with-current-continuation (lambda (cc) (set! produce-next-value cc) (iterator-return (list value)))))) (iterator-return '())))) (lambda () (call-with-current-continuation (lambda (return) (set! iterator-return return) (produce-next-value 'dummy)))))) Example use, response of the Scheme system prepended with ==>. (define (internal-iterator f) (f 1) (f 2) (f 3) (f 4)) (define external-iterator (externalize internal-iterator)) (external-iterator) ==> (1) (external-iterator) ==> (2) (external-iterator) ==> (3) (external-iterator) ==> (4) (external-iterator) ==> () This is a nice example, but should be moved to ExternalIterationUsingContinuations. See also CallWithCurrentContinuation CategoryContinuation ---- CategoryObjectFunctionalPatterns