Solution (source code)

= Solution

The source comment saying that `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 $n$ source elements and return the next one, repeatedly. Require $n\geq0$. A <lookahead iterator> must determine whether a complete group of $n+1$ 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")
      }
    }
  }
}
``
The <iterator> owns consumption of `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`.

For source elements $a_1,\ldots,a_m$, the result is
$$
\boxed{a_{n+1},a_{2(n+1)},\ldots,a_{\lfloor m/(n+1)\rfloor(n+1)}.}
$$
The extra storage is $O(1)$ and each source element is consumed at most once. `hasNext` may physically consume and cache source elements: an arbitrary <iterator> has no non-consuming length query.