iterator.pony

interface Iterator[A]
  """

  Iterators generate a series of values, one value at a time on each call to `next()`.

  An Iterator is considered exhausted, once its `has_next()` method returns `false`.
  Thus every call to `next()` should be preceeded with a call to `has_next()` to
  check for exhaustiveness.

  ## Usage

  Given the rules for using Iterators mentioned above, basic usage
  of an iterator looks like this:

  ```pony
  while iterator.has_next() do
    let elem = iterator.next()?
    // do something with elem
  end
  ```

  The `For`-loop provides a more concise way of iteration:

  ```pony
  for elem in iterator do
    // do something with elem
  end
  ```

  Iteration using `While` is more flexible as it allows to continue iterating if a call to `next()` errors.
  The `For`-loop does not allow this.

  ## Implementing Iterators

  Iterator implementations need to adhere to the following rules to be considered well-behaved:

  * If the Iterator is exhausted, `has_next()` needs to return `false`.
  * Once `has_next()` returned `false` it is not allowed to switch back to `true`
    (Unless the Iterator supports rewinding)
  * `has_next()` does not change its returned value if `next()` has not been called.
    That means, that between two calls to `next()` any number of calls to `has_next()`
    need to return the same value. (Unless the Iterator supports rewinding)
  * A call to `next()` erroring does not necessarily denote exhaustiveness.

  ### Example

  ```pony
  // Generates values from `from` to 0
  class ref Countdown is Iterator[USize]
    var _cur: USize
    var _has_next: Bool = true

    new ref create(from: USize) =>
      _cur = from

    fun ref has_next(): Bool =>
      _has_next

    fun ref next(): USize =>
      let elem = _cur = _cur - 1
      if elem == 0 then
        _has_next = false
      end
      elem
  ```

  """

  fun ref has_next(): Bool
    """
    Returns `true` if this Iterator is not yet exhausted.
    That means that a value returned from a subsequent call to `next()`
    is a valid part of this iterator.

    Returns `false` if this Iterator is exhausted.

    The behavior of `next()` after this function returned `false` is undefined,
    it might throw an error or return values which are not part of this Iterator.
    """

  fun ref next(): A ?
    """
    Generate the next value.

    This might error, which does not necessarily mean that the Iterator is exhausted.
    """