Solution (source code)

= 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.