Skip to content
CryoCryo home
Stdlibcore

iter

import std::core::iter; — in the prelude · source

Iterator

type trait Iterator {
    type Item;
    next(mut &this) -> Option<This::Item>;
    count(mut &this) -> u64;
    fold<Acc>(mut &this, initial: Acc, f: (Acc, This::Item) -> Acc) -> Acc;
    for_each(mut &this, f: (This::Item) -> void) -> void;
    take(this, n: u64) -> TakeIter<This>;
    skip(this, n: u64) -> SkipIter<This>;
    map<B>(this, f: (This::Item) -> B) -> MapIter<This, B>;
    filter(this, pred: (This::Item) -> boolean) -> FilterIter<This>;
    chain<J>(this, other: J) -> ChainIter<This, J>;
    enumerate(this) -> EnumerateIter<This>;
    zip<J>(this, other: J) -> ZipIter<This, J>;
    any(mut &this, pred: (This::Item) -> boolean) -> boolean;
    all(mut &this, pred: (This::Item) -> boolean) -> boolean;
    find(mut &this, pred: (This::Item) -> boolean) -> Option<This::Item>;
    min(mut &this) -> Option<This::Item>
    where This::Item: Ord;
    max(mut &this) -> Option<This::Item>
    where This::Item: Ord;
}

Iterator has exactly one required method — next — and everything else is derived from it. for (x in seq) drives the scrutinee through this trait, so anything that implements it works in a for loop. Item is an associated type; implement Iterator<T> for X is positional sugar for binding it.

type struct Counter { n: i32; }

implement trait Iterator<i32> for struct Counter {
    next(mut &this) -> Option<i32> {
        if (this.n >= 5) { return Option<i32>::None; }
        this.n = this.n + 1;
        return Option<i32>::Some(this.n);
    }
}

mut c: Counter = Counter { n: 0 };
for (v in c.take(3)) { println(f"{v}"); }

Lazy adapters

Each of these returns a wrapper that is itself an Iterator, so they compose. Nothing is computed until something consumes the chain.

AdapterYields
take(n)At most the first n elements.
skip(n)Everything after the first n.
map<B>(f)f applied to each element.
filter(pred)Only the elements where pred holds.
chain<J>(other)All of this, then all of other (same Item type).
enumerate()Pair<u64, Item>.first is the 0-based index.
zip<J>(other)Pair<Item, B>, stopping when either side runs out.

f and pred must be non-capturing — a plain function or a non-capturing lambda.

enumerate and zip yield Pair rather than a tuple because Cryo has no heterogeneous tuple literal.

The adapter types

type struct TakeIter<I> {
    inner:     I;
    remaining: u64;

    static new(inner: I, n: u64) -> TakeIter<I>;
}

type struct SkipIter<I> {
    inner:     I;
    remaining: u64;

    static new(inner: I, n: u64) -> SkipIter<I>;
}

type struct MapIter<I, O> {
    inner: I;

    f: (I::Item) -> O;
    static new(inner: I, f: (I::Item) -> O) -> MapIter<I, O>;
}

type struct FilterIter<I> {
    inner: I;

    pred: (I::Item) -> boolean;
    static new(inner: I, pred: (I::Item) -> boolean) -> FilterIter<I>;
}

type struct ChainIter<I, J> {
    first:      I;
    second:     J;
    first_done: boolean;

    static new(first: I, second: J) -> ChainIter<I, J>;
}

type struct EnumerateIter<I> {
    inner: I;
    index: u64;

    static new(inner: I) -> EnumerateIter<I>;
}

type struct ZipIter<I, J> {
    first:  I;
    second: J;

    static new(first: I, second: J) -> ZipIter<I, J>;
}

The wrappers the adapters return are public structs, so you can name one in a signature when the opaque implement Iterator<T> is not enough. Each is an Iterator in turn; their impls are listed under Implementors.

Eager consumers

ConsumerReturns
count()u64 — walks the iterator to count, consuming it.
fold<Acc>(initial, f)Acc
for_each(f)void
any(pred) / all(pred)boolean — both short-circuit.
find(pred)Option<Item>
min() / max() (where Item: Ord)Option<Item>

On ties min keeps the first minimal element and max keeps the last maximal one, matching the conventional behaviour.

The adapters resolve on any concrete Iterator receiver, including your own structs. Re-adapting a local whose type is the opaque implement Iterator<T> works when its initialiser is a concrete constructor (mut it: implement Iterator<i32> = Range<i32>::new(0, 10); it.take(3)); a local initialised from a producer that itself returns an opaque iterator is still restricted, so chain directly off the source in that case.

Implementors

Every iterator in the library, including the adapters above and the by-reference cursors the containers hand out:

implement<I, A> trait Iterator<A> for struct TakeIter<I>
where I: Iterator<A>

implement<I, A> trait Iterator<A> for struct SkipIter<I>
where I: Iterator<A>

implement<I, O> trait Iterator<O> for struct MapIter<I, O>
where I: Iterator

implement<I> trait Iterator<I::Item> for struct FilterIter<I>
where I: Iterator

implement<I, J, A> trait Iterator<A> for struct ChainIter<I, J>
where I: Iterator<A>, J: Iterator<A>

implement<I> trait Iterator<Pair<u64, I::Item>> for struct EnumerateIter<I>
where I: Iterator

implement<I, J, A, O> trait Iterator<Pair<A, O>> for struct ZipIter<I, J>
where I: Iterator<A>, J: Iterator<O>

implement<T> trait Iterator<T*> for struct RefIter<T>   // std::collections::array

implement<I, T> trait Iterator<T> for struct CopiedIter<I>
where I: Iterator<T*>, T: Copy   // std::collections::array

implement<I, T> trait Iterator<T> for struct ClonedIter<I>
where I: Iterator<T*>, T: Clone   // std::collections::array

implement<K, V> trait Iterator<Pair<K, V>> for struct HashMapIter<K, V>
where K: Copy, V: Copy   // std::collections::hashmap

implement<K, V> trait Iterator<K> for struct KeysIter<K, V>   // std::collections::hashmap

implement<K, V> trait Iterator<V> for struct ValuesIter<K, V>   // std::collections::hashmap

implement<K, V> trait Iterator<Pair<K*, V*>> for struct EntriesRefIter<K, V>   // std::collections::hashmap

implement<K, V> trait Iterator<K*> for struct KeysRefIter<K, V>   // std::collections::hashmap

implement<K, V> trait Iterator<V*> for struct ValuesRefIter<K, V>   // std::collections::hashmap

implement<T> trait Iterator<T> for struct HashSetIter<T>
where T: Copy   // std::collections::hashset

implement<T> trait Iterator<T*> for struct HashSetRefIter<T>   // std::collections::hashset

implement trait Iterator<Str> for struct SplitIter   // std::collections::str

implement trait Iterator<u32> for struct Chars   // std::collections::str

implement trait Iterator<Pair<u64, u32>> for struct CharIndices   // std::collections::str

implement<T> trait Iterator<T> for struct Range<T>
where T: Step   // std::core::ops

implement<T> trait Iterator<T> for struct RangeInclusive<T>
where T: Step   // std::core::ops

implement<T> trait Iterator<T> for struct SliceIter<T>   // std::core::slice

implement trait Iterator<DirEntry> for struct ReadDir   // std::fs::dir