= Solution
These methods consume the receiver's remaining sequence; `exists` stops as soon as it finds a witness:
``
trait RichIter[T] extends Iter[T] {
def foreach(f: T => Unit): Unit = {
while (hasNext) f(next())
}
def exists(p: T => Boolean): Boolean = {
while (hasNext) {
if (p(next())) return true
}
false
}
def foldLeft[U](x: U)(f: (U,T) => U): U = {
var result = x
while (hasNext) result = f(result, next())
result
}
}
``
After $j$ consumed elements, `foreach` has invoked its callback on exactly that prefix, `exists` has found no witness in it unless it has already returned, and the <left fold> accumulator is the fold of that prefix in its original order. These <loop invariants> prove the finite-sequence results. On an infinite sequence, `exists` may still terminate when it reaches a witness; a full traversal or fold generally does not. To retain the original cursor, a caller can invoke the operation on a suitable copy.
Back to article page