Represent a generated sequence by shared memoized lazy list cells and let each iterator hold its own current cell reference. Copy that reference into a new iterator object. Advancing one cursor changes no other cursor, while every cell's future tail is generated once. Thus even a privately stateful generator can supply identical future values to independently consumed snapshots, provided its state is owned by this shared sequence and not mutated externally. Retained older cursors can keep cached prefixes alive. [ref]
Use a shared memoized lazy list with a separate mutable cursor in each iterator:
import scala.collection.immutable.Stream

class FunIter[T] private (
    private var rest: Stream[T]) extends Iter[T] {

  def this(v: T, f: T => T) = this(Stream.iterate(v)(f))

  def hasNext: Boolean = true

  def next(): T = {
    val result = rest.head
    rest = rest.tail
    result
  }

  def copy(): Iter[T] = new FunIter[T](rest)
}
For a total step function, the stream is infinite and its values are . At every call, rest starts with the next unconsumed value. Copying that reference gives a new cursor at exactly the same position; later cursor assignments are independent.
The memoized iterator snapshot is useful for the next part: if f owns private mutable state, advancing either cursor realizes a previously unknown tail only once, and both copies can then read the same cached values. Merely constructing new FunIter(current, f) would share the mutable closure while generating two independent futures, which could diverge. Memoization instead makes the generated sequence shared and the consumption positions independent. The closure must not be mutated externally, and generic element payloads are shared rather than deep-copied. Retaining an old cursor can retain cached cells.[ref]