Iterators generate a series of values, one value at a time on each call to
An Iterator is considered exhausted, once its
has_next() method returns
Thus every call to
next() should be preceeded with a call to
check for exhaustiveness.
Given the rules for using Iterators mentioned above, basic usage of an iterator looks like this:
while iterator.has_next() do let elem = iterator.next()? // do something with elem end
For-loop provides a more concise way of iteration:
for elem in iterator do // do something with elem end
While is more flexible as it allows to continue iterating if a call to
For-loop does not allow this.
Iterator implementations need to adhere to the following rules to be considered well-behaved:
- If the Iterator is exhausted,
has_next()needs to return
falseit 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.
// Generates values from `from` to 0 class Countdown is Iterator[USize] var _cur: USize var _has_next: Bool = true new create(from: USize) => _cur = from fun has_next(): Bool => _has_next fun next(): USize => let elem = _cur = _cur - 1 if elem == 0 then _has_next = false end elem
interface Iterator[A: A]
true if this Iterator is not yet exhausted.
That means that a value returned from a subsequent call to
is a valid part of this iterator.
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 has_next() : Bool
- Bool val
Generate the next value.
This might error, which does not necessarily mean that the Iterator is exhausted.
fun next() : A ?
- A ?