Iterators

Iterator interfaces and iterable collection support.

std.iter contains the static iteration protocol used by for loops and the small iterator facade used by the root std.iter(value) helper. This is a deliberately small 0.0.0-dev surface, not a full lazy-iterator hierarchy.

import {
    Iterable
} from std.iter;

The iterable interface shape is:

interface Iterable<T, Iter> {
    fn iter(self) -> Iter;
}

The iterator returned by iter() must expose next(self) -> T?. Returning null ends the loop.

Root Helper

The auto-preluded root std namespace exposes std.iter(value) for array and slice-backed pipelines. It does not import the std.iter module namespace; use an ordinary import when the Iterable interface name is needed.

fn is_three(value: i32) -> bool {
    return value == 3;
}

fn less_than_four(value: i32) -> bool {
    return value < 4;
}

fn add(acc: i32, value: i32) -> i32 {
    return acc + value;
}

fn main() {
    let values: [i32] = [1, 2, 3, 4];

    let total = std.iter(values).skip(1).take(2).fold(0, add);
    assert total == 5;

    assert std.iter(values).count() == 4;
    assert std.iter(values).next_or(0) == 1;
    assert std.iter(values).any(is_three);
    assert std.iter(values).all(less_than_four) == false;
}

Current pipeline methods are next, next_or, skip, take, fold, any, all, and count. Broader adapters such as map, filter, zip, chain, flat_map, and collection builders are not public yet.

Custom Iterable

import {
    Iterable
} from std.iter;

struct RangeIter {
    current: i32,
    end: i32,

    fn next(self) -> i32? {
        if self.current < self.end {
            let value = self.current;
            self.current = self.current + 1;
            return value;
        }
        return null;
    }
}

struct Range: Iterable<i32, RangeIter> {
    start: i32,
    end: i32,

    fn iter(self) -> RangeIter {
        return RangeIter {
            current: self.start,
            end: self.end,
        };
    }
}

fn main() {
    let range = Range { start: 1, end: 4 };
    let sum = 0;

    for value in range {
        sum = sum + value;
    }

    assert sum == 6;
}

for index, value in range also works. The index starts at 0 and increments once for each value produced by next.

Arrays

std.collections.Array<T> implements Iterable<const &T, ArrayIter<T>>. ArrayIter<T>.next() returns const &T?, so normal array iteration borrows each element. For copyable elements, Array.copy_iter() returns ArrayCopyIter<T> whose next() yields T?.

import {
    Array
} from std.collections;

fn main() {
    let values = Array<i32>();
    try values.append(1);
    try values.append(2);

    let sum = 0;
    for value in values {
        sum = sum + value;
    }

    assert sum == 3;
}

The compiler checks the iterable protocol statically. Interfaces are constraints for analysis; they are not runtime objects.