= Solution
Map a pure, terminating function only when a value is demanded; use the adapters to obtain the <cursor> form with caching:
``
def map[T, U](f: T => U, it: Iter[T]): Iter[U] = new Iter[U] {
def hasNext: Boolean = it.hasNext
def next(): U = {
require(it.hasNext, "empty iterator")
f(it.next())
}
}
def map[T, U](f: T => U, cur: Cursor[T]): Cursor[U] =
asCursor(map(f, asIter(cur)))
``
Each demanded output is the function applied to the corresponding input, preserving order and lazy access even for an infinite <sequence>. The <cursor> adapter caches its mapped current value, so repeated reads need not recompute `f`. Totality/purity of `f` is the usual assumption for the mathematical <sequence>-map <postcondition>; an exception-throwing or state-changing function would need additional behavioral clauses.
\b[Both functions may be named `map` because their second parameter types differ], `Iter[T]` versus `Cursor[T]`. <Method overloading> selects the applicable signature; its distinction is not based solely on the return type.
Back to article page