Iterators
Source: runtime/iterator.pep
Iterator
trait Iterator<T>
Something a for loop can step through, one element at a time.
for (var x in source) drives a source that declares next() and
current() directly: it calls next() before each pass and binds
current() to the loop variable while next() returns true. A type whose
for loop should go through a separate iterator implements Iterable<T>
instead. A type with neither protocol is a compile error in a for loop.
The loop goes by the methods a type has, so declaring the trait is
optional. Declaring it (extend Foo with Iterator<int>;) checks that
the methods match and lets the type be used as an Iterator<int> value,
which a for loop drives through the trait.
Type parameters
T— the type of the elements produced
See also
Iterable
Example
struct Countdown {
int remaining;
int now;
construct(this.remaining = 0) {}
bool next() {
if (remaining == 0) {
return false;
}
now = remaining;
remaining = remaining - 1;
return true;
}
int current() {
return now;
}
}
extend Countdown with Iterator<int>;
main(): int {
var total = 0;
for (int n in Countdown(3)) {
total = total + n; # visits 3, 2, 1
}
return total;
}
Methods
next
next(): bool
Advances to the next element.
The first call moves to the first element, if any. Once it returns false it must keep returning false.
Returns
- true if there is a current element, false when the elements are exhausted
current
current(): T
Returns the element the last successful next() moved to.
Calling it before the first next(), or after next() returned false,
is an error; the runtime’s iterators panic in that case.
Returns
- the current element
map
map<U>(transform: (T) => U): MapIterator<T, U>
Returns an iterator over transform applied to each element, in order.
Lazy: transform runs once per element, as the result is advanced, and
the result advances this iterator. Every type that declares
Iterator<T> gets this method.
Type parameters
U— the typetransformreturns
Parameters
transform— the function applied to each element
Returns
- a
MapIterator<T, U>over the transformed elements
Example
var names = Array<String>();
for (var size in names.iterate().map((name) => name.size)) {
print(size);
}
filter
filter(keep: (T) => bool): FilterIterator<T>
Returns an iterator over the elements for which keep returns true, in
order.
Lazy: keep runs once per element, as the result is advanced, and the
result advances this iterator. Every type that declares Iterator<T>
gets this method.
Parameters
keep— the test an element must pass
Returns
- a
FilterIterator<T>over the elements that pass
Example
var nums = Array<int>();
for (var even in nums.iterate().filter((n) => n % 2 == 0)) {
print(even);
}
enumerate
enumerate<TIndex=ulong>(): EnumerateIterator<T, TIndex>
Returns an iterator over the elements paired with their positions:
(0, first), (1, second), and so on.
Lazy, like map. Destructure the pair in the loop to name both parts.
The positions count in ulong, like Array.count; name another
integer type to count in it (enumerate<int>()). Every type that
declares Iterator<T> gets this method.
Type parameters
TIndex— the integer type of the positions,ulongby default
Returns
- an
EnumerateIterator<T, TIndex>over(index, element)tuples
Example
var names = ["Ada", "Grace"];
for (var (i, name) in names.iterate().enumerate()) {
print($"{i}: {name}"); # 0: Ada, then 1: Grace
}
zip
zip<U>(other: Iterator<U>): ZipIterator<T, U>
Returns an iterator over pairs of this iterator’s elements and
other’s, in step: (first, other's first), and so on. It stops when
either runs out.
Lazy, like map. Every type that declares Iterator<T> gets this
method.
Type parameters
U— the type ofother’s elements
Parameters
other— the iterator whose elements form the second half of each pair
Returns
- a
ZipIterator<T, U>over(element, other element)tuples
Example
var names = ["Ada", "Grace"];
var ages = [36, 45];
for (var (name, age) in names.iterate().zip(ages.iterate())) {
print($"{name} is {age}");
}
to_array
to_array(): Array<T>
Returns a new Array holding the remaining elements, in order.
Runs the iteration to the end. Like the adapters, it works on a copy
of the iterator, so a value iterator (every runtime iterator is one)
is left where it was. Every type that declares Iterator<T> gets this
method.
Returns
- the elements, possibly none
Example
var evens = (1..>10).filter((n) => n % 2 == 0).to_array(); # [2, 4, 6, 8, 10]
MapIterator
[Value] struct MapIterator<T, U>
The iterator Iterator.map returns: each element of the source iterator,
passed through the transform function.
Type parameters
T— the type of the source’s elementsU— the type of the elements produced
See also
Iterator.map
Constructor
MapIterator()
construct(source: Iterator<T>, transform: (T) => U)
Makes an iterator over transform applied to the elements of source.
Parameters
source— the iterator to transformtransform— the function applied to each element
Methods
next
next(): bool
Advances to the next element, and applies the transform function to it.
Returns
- true if there is a current element, false when the source is exhausted
current
current(): U
Returns the transformed element the last successful next() produced.
Returns
- the current element
FilterIterator
[Value] struct FilterIterator<T>
The iterator Iterator.filter returns: the elements of the source
iterator that the test function accepts.
Type parameters
T— the type of the elements
See also
Iterator.filter
Constructor
FilterIterator()
construct(source: Iterator<T>, keep: (T) => bool)
Makes an iterator over the elements of source that keep accepts.
Parameters
source— the iterator to filterkeep— the test an element must pass
Methods
next
next(): bool
Advances to the next element that the test function accepts.
Returns
- true if there is a current element, false when the source is exhausted
current
current(): T
Returns the element the last successful next() moved to.
Returns
- the current element
EnumerateIterator
[Value] struct EnumerateIterator<T, TIndex>
The iterator Iterator.enumerate returns: each element of the source
iterator, paired with its position.
Type parameters
T— the type of the source’s elementsTIndex— the integer type of the positions
See also
Iterator.enumerate
Constructor
EnumerateIterator()
construct(source: Iterator<T>)
Makes an iterator over the elements of source, numbered from 0.
Parameters
source— the iterator to number
Methods
next
next(): bool
Advances to the next element.
Returns
- true if there is a current element, false when the source is exhausted
current
current(): (TIndex, T)
Returns the element the last successful next() moved to, with its
index.
Returns
- the current
(index, element)pair
ZipIterator
[Value] struct ZipIterator<T, U>
The iterator Iterator.zip returns: the elements of two iterators,
paired in step, until either runs out.
Type parameters
T— the type of the first iterator’s elementsU— the type of the second iterator’s elements
See also
Iterator.zip
Constructor
ZipIterator()
construct(first: Iterator<T>, second: Iterator<U>)
Makes an iterator over the elements of first and second, paired.
Parameters
first— the iterator giving the first half of each pairsecond— the iterator giving the second half of each pair
Methods
next
next(): bool
Advances both iterators. second is not advanced once first has
run out.
Returns
- true if both have a current element, false when either is exhausted
current
current(): (T, U)
Returns the pair the last successful next() moved to.
Returns
- the current
(first element, second element)pair
Iterable
trait Iterable<T>
Something that hands out an Iterator<T> over its elements, such as
Array<T> and String (which yields one code point at a time, as a
String).
for (var x in source) calls source.iterate() once, then drives the
returned iterator with next() and current(). When a type declares both
iterate() and next()/current(), the loop uses iterate().
Type parameters
T— the type of the elements produced
See also
Iterator
Example
var nums = Array<int>();
nums.append(1);
nums.append(2);
var total = 0;
for (var x in nums) {
total = total + x;
}
Methods
iterate
iterate(): Iterator<T>
Returns a new iterator positioned before the first element.
The result may be any type that satisfies Iterator<T> (for example
ArrayIterator<T>); each call starts a fresh, independent pass.
Returns
- an iterator over the elements