The source comment saying that The iterator owns consumption of
hasNext checks whether the sequence is empty is read in the standard sense “whether another element exists”; the method must return true for a nonempty logical sequence. The example fixes the meaning: skip source elements and return the next one, repeatedly. Require . A lookahead iterator must determine whether a complete group of elements exists, since a short final group contributes no result.def skipIter[T](it: Iter[T], n: Int): Iter[T] = {
require(n >= 0)
new Iter[T] {
private var prepared = false
private var cached: Option[T] = None
private def prepare(): Unit = {
if (!prepared) {
var skipped = 0
while (skipped < n && it.hasNext) {
it.next(); skipped += 1
}
cached =
if (skipped == n && it.hasNext) Some(it.next())
else None
prepared = true
}
}
def hasNext: Boolean = { prepare(); cached.nonEmpty }
def next(): T = {
prepare()
cached match {
case Some(v) =>
cached = None; prepared = false; v
case None => throw new NoSuchElementException("skipIter.next")
}
}
}
}it; clients must not independently advance the wrapped source. A prepared Some(v) is exactly the next selected source element, and None means no complete group remains. Repeated hasNext calls use the cached decision, and next also works without a preceding hasNext. Using Option[T] avoids an invalid generic sentinel value, including when a valid element is null.