fp.iteration¶
fp.iteration provides lazy mapping, filtering and scans, together with folds,
reductions and searches over native iterators and owned collections. The
iteration tutorial follows values through a lazy
chain and shows how a terminal operation consumes them.
Lazy adapters, folds, reductions and terminal operations over native iterators.
Every operation consumes a source: a native iterator, used as it is and
never restarted, or an owned collection (any IterableOwned, such as List,
Set or Dict), consumed as iter(values^) would. Pass values^ to consume
a collection, or iter(values) to borrow it. Standard adapters (chain, zip,
enumerate, take, drop, peekable, ...) come from std.iter and
std.itertools and combine freely with these.
iterated(source) adds consuming method syntax to the same native iterators:
iterated(values^).map(f).filter(p).to_list(). Its Iter wrapper implements
Iterator and IterableOwned, so standard consuming adapters accept it
directly. Wrap a standard adapter's result with iterated to continue chaining.
to_list() and collect_list() are alias methods for the free collect_list.
Named chains are consumed explicitly, as in stream^.to_list().
Lazy adapters (map, filter, filter_map, flatten, flat_map,
scan_left) are native iterators whose advancement raises only
StopIteration:
- Construction is inert: nothing is pulled and no callback runs until the first
next. - They are fused: after a source reports exhaustion it is never pulled again.
- There is no lookahead: each output pulls only what it needs.
- Abandoning one destroys its owned state without evaluating the rest.
Lazy callbacks do not raise, because a native iterator can raise only
StopIteration; to carry a domain failure, yield Result elements and
aggregate them with collect_results. A callback is a plain function, a
capturing closure or, for map, filter_map, flat_map and scan_left, a
shared-receiver Unary/Binary value such as a Partial. Move a closure that
owns non-trivial state in with callback^. Owners of borrowed captures must
stay alive and unmoved while the adapter is used. A generic function that
returns an adapter names its type with MapIterator, ScanIterator,
FilterIterator, FilterMapIterator or FlatMapIterator, declares
I: Iterator and where I.Element == T, and builds the value through the
function; the types add no storage, and the source origin stays part of the
type.
Folds and terminals (fold_left, fold_until, reduce,
reduce_optional, collect_list, find, any, all) run at once:
| Operation | Non-empty input | Empty input |
|---|---|---|
fold_left(step, initial, source) |
n calls of step(var A, var T) -> A, in order |
initial, no calls |
reduce(step, source, initial=value) |
The same as fold_left |
initial, no calls |
reduce(step, source) |
The first element seeds the accumulator; n - 1 calls |
Raises EmptyReductionError |
reduce_optional(step, source) |
As above, wrapped in Optional |
None |
fold_until(step, initial, source) |
Each call returns ControlFlow[B, A]; Break(b) returns at once |
Continue(initial) |
collect_list(source) |
A List of every element, moved |
An empty list |
find(p, source) |
The first accepted element | None |
any(p, source) / all(p, source) |
Stops at the first decisive element | False / True |
Steps are never reassociated. Pure and raising callbacks have separate
overloads, and a callback's error type propagates unchanged; a callback that
raises StopIteration fails as a callback, never as exhaustion. The first
decisive result or failure stops without another pull. On failure, native
cleanup destroys the source, the current accumulator and the pulled element;
side effects are not rolled back. Every operation makes O(n) callback calls,
or fewer after an early stop, with constant extra state.
A generic function forwards to these with the native callback constraint and
where I.Element == T. A raising wrapper passes E=E at every call and must
not read F.E or F.T from a callback type: Mojo 1.1 does not reliably expose
those attributes through a precompiled package. Keep the parameter names shown
in the tutorial's generic examples; on Mojo 1.1 some renamings lose callback
conformance.
Summary¶
| Name | Kind | Summary |
|---|---|---|
all |
function | Whether predicate accepts every element; stops at the first rejected one. |
any |
function | Whether predicate accepts some element; stops at the first accepted one. |
collect_list |
function | Collect every element of a source into a List, in order. |
filter |
function | Lazily keep the elements predicate accepts. |
filter_map |
function | Lazily apply function and keep the present results. |
find |
function | Return the first element predicate accepts, without pulling another. |
flat_map |
function | Lazily apply function and concatenate the inner sources it returns: flatten(map(function, source)). |
flatten |
function | Lazily concatenate the inner sources a source yields. |
fold_left |
function | Fold a source from the left: step(... step(step(initial, x0), x1) ..., xn). |
fold_until |
function | Fold until a step returns Break, without pulling another element. |
iterated |
function | Start a consuming method chain over an iterator or owned collection. |
map |
function | Lazily apply function to each element: function(x0), function(x1), .... |
reduce |
function | Reduce a source from an initial value: the same as fold_left. |
reduce_optional |
function | Reduce a source with its first element as the accumulator; empty input gives None. |
scan_left |
function | Lazily yield initial and then the accumulator after each step: n + 1 values for n elements. |
EmptyReductionError |
struct | The error of reduce without an initial value on an empty source. |
Iter |
struct | A native iterator with consuming transformation and terminal methods. |
ReductionStepError |
struct | A reduction step's error, kept distinct from empty input. |
FilterIterator |
alias | The type filter returns, for a generic function's return annotation. |
FilterMapIterator |
alias | The type filter_map returns, for a generic function's return annotation. |
FlatMapIterator |
alias | The type flat_map returns, for a generic function's return annotation. |
MapIterator |
alias | The type map returns, for a generic function's return annotation. |
ReductionError |
alias | The error of a raising reduce without an initial value: empty input, or the step's error. |
ScanIterator |
alias | The type scan_left returns, for a generic function's return annotation. |
Functions¶
all¶
Source: fp/iteration/adapters.mojo
def all[T, I, //, F: def(T) -> Bool](
predicate: F,
var source: I,
) -> Bool where _Source[I].Element == T
Whether predicate accepts every element; stops at the first rejected one.
Parameters
T(Movable & Deinitable, inferred): The element type.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.F(def(T) -> Bool): The predicate's type: a plain function or a closure.
Arguments
predicate(F): The predicate, borrowed; it borrows each candidate.source(var I): The source, consumed.
Returns
Bool: False at the first rejected element; True for an empty source.
2 more overloads
Whether a raising predicate accepts every element; its error stops the search.
def all[T, I, E, //, F: def(T) raises E -> Bool](
predicate: F,
var source: I,
) raises E -> Bool where _Source[I].Element == T
Whether a `BorrowCallable` predicate accepts every element.
def all[I, C: BorrowCallable](
predicate: C,
var source: I,
) raises C.Failure -> Bool where conforms_to(_Source[I].Element, Movable & Deinitable) and C.Payload == _Source[I].Element and C.Result == Bool
any¶
Source: fp/iteration/adapters.mojo
def any[T, I, //, F: def(T) -> Bool](
predicate: F,
var source: I,
) -> Bool where _Source[I].Element == T
Whether predicate accepts some element; stops at the first accepted one.
Parameters
T(Movable & Deinitable, inferred): The element type.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.F(def(T) -> Bool): The predicate's type: a plain function or a closure.
Arguments
predicate(F): The predicate, borrowed; it borrows each candidate.source(var I): The source, consumed.
Returns
Bool: True at the first accepted element; False for an empty source.
2 more overloads
Whether a raising predicate accepts some element; its error stops the search.
def any[T, I, E, //, F: def(T) raises E -> Bool](
predicate: F,
var source: I,
) raises E -> Bool where _Source[I].Element == T
Whether a `BorrowCallable` predicate accepts some element.
def any[I, C: BorrowCallable](
predicate: C,
var source: I,
) raises C.Failure -> Bool where conforms_to(_Source[I].Element, Movable & Deinitable) and C.Payload == _Source[I].Element and C.Result == Bool
collect_list¶
Source: fp/iteration/adapters.mojo
def collect_list[T, I](var source: I) -> List[T] where _Source[I].Element == T
Collect every element of a source into a List, in order.
Parameters
T(Movable & Deinitable): The element type.I(Movable & Deinitable): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.
Arguments
source(var I): The source, consumed.
Returns
List[T]: A List of the elements, moved in; empty for an empty source.
filter¶
Source: fp/iteration/adapters.mojo
def filter[T, I, //](
function: def(T) thin -> Bool,
var source: I,
) -> _Filter[T, _Source[I]] where _Source[I].Element == T
Lazily keep the elements predicate accepts.
The predicate borrows each candidate, and the original element is yielded unchanged. Each output pulls until a candidate is accepted.
Parameters
T(Movable & Deinitable, inferred): The element type.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.
Arguments
function(def(T) thin -> Bool): The predicate, a plain function, stored.source(var I): The source, consumed.
Returns
A FilterIterator, a native iterator of the accepted elements.
2 more overloads
Lazily keep the elements a closure predicate accepts.
def filter[T, I, //, F: _LazyPredicate[T]](
var function: F,
var source: I,
) -> _Filter[T, _Source[I], F] where _Source[I].Element == T
Lazily keep the elements a `BorrowCallable` predicate accepts.
def filter[I, C: BorrowCallable](
var predicate: C,
var source: I,
) -> _Filter[_Source[I].Element, _Source[I], C] where conforms_to(_Source[I].Element, Movable & Deinitable) and C.Payload == _Source[I].Element and C.Result == Bool and C.Failure == Never
filter_map¶
Source: fp/iteration/adapters.mojo
def filter_map[T, U, I, //](
function: def(var T) thin -> Optional[U],
var source: I,
) -> _FilterMap[T, U, _Source[I]] where _Source[I].Element == T
Lazily apply function and keep the present results.
Each element is moved into the function. Only None is skipped: a present
Result.Err is an ordinary output.
Parameters
T(Movable & Deinitable, inferred): The element type.U(Movable & Deinitable, inferred): The type of a present result.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.
Arguments
function(def(var T) thin -> Optional[U]): A plain function returningOptional[U], stored.source(var I): The source, consumed.
Returns
A FilterMapIterator, a native iterator of the present results.
2 more overloads
Lazily apply a closure returning `Optional[U]` and keep the present results.
def filter_map[T, U, I, //, F: _LazyOptional[T, U]](
var function: F,
var source: I,
) -> _FilterMap[T, U, _Source[I], F] where _Source[I].Element == T
Lazily apply a library `Unary` value returning `Optional[U]`; name `U` explicitly.
def filter_map[U, I, F: Unary](
var function: F,
var source: I,
) -> _FilterMap[F.Arg, U, _Source[I], F] where _Source[I].Element == F.Arg and F.Out == Optional[U] and F.Error == Never
find¶
Source: fp/iteration/adapters.mojo
def find[T, I, //, F: def(T) -> Bool](
predicate: F,
var source: I,
) -> Optional[T] where _Source[I].Element == T
Return the first element predicate accepts, without pulling another.
The predicate borrows each candidate; the accepted element is returned as it is, and rejected ones are destroyed.
Parameters
T(Movable & Deinitable, inferred): The element type.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.F(def(T) -> Bool): The predicate's type: a plain function or a closure.
Arguments
predicate(F): The predicate, borrowed.source(var I): The source, consumed.
Returns
Optional[T]: The first accepted element, or None when there is none.
2 more overloads
Return the first accepted element with a raising predicate; its error stops the search.
def find[T, I, E, //, F: def(T) raises E -> Bool](
predicate: F,
var source: I,
) raises E -> Optional[T] where _Source[I].Element == T
Return the first element a `BorrowCallable` predicate accepts.
def find[I, C: BorrowCallable](
predicate: C,
var source: I,
) raises C.Failure -> Optional[_Source[I].Element] where conforms_to(_Source[I].Element, Movable & Deinitable) and C.Payload == _Source[I].Element and C.Result == Bool
flat_map¶
Source: fp/iteration/adapters.mojo
def flat_map[T, S, I](
function: def(var T) thin -> S,
var source: I,
) -> _Flatten[_Map[T, S, _Source[I]], S] where _Source[I].Element == T
Lazily apply function and concatenate the inner sources it returns: flatten(map(function, source)).
The returned inner iterator or iterable is kept until it is exhausted or the adapter is abandoned.
Parameters
T(Movable & Deinitable): The element type.S(Movable & Deinitable): The returned inner source's type: a native iterator or an owned iterable.I(Movable & Deinitable): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.
Arguments
function(def(var T) thin -> S): A plain function, stored.source(var I): The source, consumed.
Returns
A FlatMapIterator, a native iterator of the inner elements.
2 more overloads
Lazily apply a closure and concatenate the inner sources it returns.
def flat_map[T, U, I, //, F: _LazyUnary[T, U]](
var function: F,
var source: I,
) -> _Flatten[_Map[T, U, _Source[I], F], U] where _Source[I].Element == T
Lazily apply a library `Unary` value and concatenate the inner sources it returns.
def flat_map[I, F: Unary](
var function: F,
var source: I,
) -> _Flatten[_Map[F.Arg, F.Out, _Source[I], F], F.Out] where _Source[I].Element == F.Arg and F.Error == Never
flatten¶
Source: fp/iteration/adapters.mojo
def flatten[I, S](
var source: I,
) -> _Flatten[_Source[I], S] where _Source[I].Element == S
Lazily concatenate the inner sources a source yields.
Each inner source, a native iterator or an owned iterable, is exhausted before the next outer element is pulled, and empty inner sources are skipped. An inner iterator may borrow an external owner, which must stay alive.
Parameters
I(Movable & Deinitable): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.S(Movable & Deinitable): The inner source's type.
Arguments
source(var I): The source of inner sources, consumed.
Returns
A native iterator of the inner elements, in order.
fold_left¶
Source: fp/iteration/folds.mojo
def fold_left[A, T, I, //, F: def(var A, var T) -> A](
step: F,
var initial: A,
var iterator: I,
) -> A where _Source[I].Element == T
Fold a source from the left: step(... step(step(initial, x0), x1) ..., xn).
Each element is moved into step with the accumulator, in order, and the
steps are never reassociated. The accumulator and element types may differ;
scalars, SIMD values (whose lanes are never reduced implicitly) and any other
accumulator work alike. Empty input returns initial without a call.
Parameters
A(Movable & Deinitable, inferred): The accumulator type.T(Movable & Deinitable, inferred): The element type.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.F(def(var A, var T) -> A): The step's type: a plain function or a closure.
Arguments
step(F): The step, borrowed; it is called once per element.initial(var A): The first accumulator, consumed.iterator(var I): The source, consumed.
Returns
A: The final accumulator.
2 more overloads
Fold with a raising step; its error stops the fold with its own type.
def fold_left[A, T, I, E: AnyType, //, F: def(var A, var T) raises E -> A](
step: F,
var initial: A,
var iterator: I,
) raises E -> A where _Source[I].Element == T
Fold with a library `Binary` step, such as a partial with two remaining arguments.
def fold_left[A, I, F: Binary](
step: F,
var initial: A,
var iterator: I,
) raises F.Error -> A where F.First == A and F.Second == _Source[I].Element and F.Out == A
fold_until¶
Source: fp/iteration/folds.mojo
def fold_until[A, B, T, I, //, F: def(var A, var T) -> ControlFlow[B, A]](
step: F,
var initial: A,
var iterator: I,
) -> ControlFlow[B, A] where _Source[I].Element == T
Fold until a step returns Break, without pulling another element.
Each step returns Continue(accumulator) to go on or Break(value) to stop
at once; the element that caused the break has been consumed. Exhaustion
returns Continue with the last accumulator, or initial for empty input.
Parameters
A(Movable & Deinitable, inferred): The accumulator type.B(Movable & Deinitable, inferred): The type of the value a step stops with.T(Movable & Deinitable, inferred): The element type.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.F(def(var A, var T) -> ControlFlow[B, A]): The step's type: a plain function or a closure returningControlFlow[B, A].
Arguments
step(F): The step, borrowed.initial(var A): The first accumulator, consumed.iterator(var I): The source, consumed.
Returns
ControlFlow[B, A]: The first Break, or Continue with the final accumulator.
2 more overloads
Fold until `Break` with a raising step; its error is a separate outcome from `Break`.
def fold_until[
A, B, T, I, E, //, F: def(var A, var T) raises E -> ControlFlow[B, A],
](
step: F,
var initial: A,
var iterator: I,
) raises E -> ControlFlow[B, A] where _Source[I].Element == T
Fold until `Break` with a library `Binary` step.
def fold_until[B, A, I, F: Binary](
step: F,
var initial: A,
var iterator: I,
) raises F.Error -> ControlFlow[B, A] where F.First == A and F.Second == _Source[I].Element and F.Out == ControlFlow[B, A]
iterated¶
Source: fp/iteration/chaining.mojo
def iterated[S](var source: S) -> Iter[_Source[S]]
Start a consuming method chain over an iterator or owned collection.
An iterator keeps its current position. An owned collection is consumed
through its native owned iterator. Pass iter(values) to borrow a
collection, keeping the owner alive and unmoved while the chain is used.
Construction does not pull any elements or run callbacks.
Parameters
S(Movable & Deinitable): A native iterator or anIterableOwnedcollection.
Arguments
source(var S): The source, consumed.
Returns
Iter[...]: A native Iterator and IterableOwned wrapper with chaining methods.
map¶
Source: fp/iteration/adapters.mojo
def map[T, U, I, //](
function: def(var T) thin -> U,
var source: I,
) -> _Map[T, U, _Source[I]] where _Source[I].Element == T
Lazily apply function to each element: function(x0), function(x1), ....
Each element is moved into the function, so move-only elements and results
work. Nothing is pulled until the first next, and each output pulls one
element.
Parameters
T(Movable & Deinitable, inferred): The element type.U(Movable & Deinitable, inferred): The result type.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.
Arguments
function(def(var T) thin -> U): A plain function, stored.source(var I): The source, consumed.
Returns
A MapIterator, a native iterator of the results.
2 more overloads
Lazily apply a closure; move one that owns non-trivial state in with `function^`.
def map[T, U, I, //, F: _LazyUnary[T, U]](
var function: F,
var source: I,
) -> _Map[T, U, _Source[I], F] where _Source[I].Element == T
Lazily apply a library `Unary` value, such as a partial or a composition.
def map[I, F: Unary](
var function: F,
var source: I,
) -> _Map[F.Arg, F.Out, _Source[I], F] where _Source[I].Element == F.Arg and F.Error == Never
reduce¶
Source: fp/iteration/folds.mojo
def reduce[A, T, I, //, F: def(var A, var T) -> A](
step: F,
var iterator: I,
*,
var initial: A,
) -> A where _Source[I].Element == T
Reduce a source from an initial value: the same as fold_left.
Parameters
A(Movable & Deinitable, inferred): The accumulator type.T(Movable & Deinitable, inferred): The element type.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.F(def(var A, var T) -> A): The step's type: a plain function or a closure.
Arguments
step(F): The step, borrowed; it is called once per element.iterator(var I): The source, consumed.initial(var A): The first accumulator, consumed; returned for empty input.
Returns
A: The final accumulator.
def reduce[T, I, //, F: def(var T, var T) -> T](
step: F,
var iterator: I,
) raises EmptyReductionError -> T where _Source[I].Element == T
Reduce a source with its first element as the accumulator.
Parameters
T(Movable & Deinitable, inferred): The element and accumulator type.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.F(def(var T, var T) -> T): The step's type: a plain function or a closure.
Arguments
step(F): The step, borrowed; it is called once per element after the first.iterator(var I): The source, consumed.
Returns
T: The final accumulator.
Raises
EmptyReductionError: EmptyReductionError when the source is empty.
def reduce[T, I, E, //, F: def(var T, var T) raises E -> T](
step: F,
var iterator: I,
) raises ReductionError[E] -> T where _Source[I].Element == T
Reduce with a raising step and no initial value.
Empty input and a step's error are two different failures, so they raise
two alternatives of one Variant.
Parameters
T(Movable & Deinitable, inferred): The element and accumulator type.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.E(Movable & Deinitable, inferred): The step's error type.F(def(var T, var T) raises E -> T): The step's type: a plain function or a closure that raisesE.
Arguments
step(F): The step, borrowed; it is called once per element after the first.iterator(var I): The source, consumed.
Returns
T: The final accumulator.
Raises
ReductionError[E]: ReductionError[E]: EmptyReductionError for an empty source, or
ReductionStepError[E] holding the step's error.
3 more overloads
Reduce from an initial value with a raising step; its error is kept.
def reduce[A, T, I, E, //, F: def(var A, var T) raises E -> A](
step: F,
var iterator: I,
*,
var initial: A,
) raises E -> A where _Source[I].Element == T
Reduce from an initial value with a library `Binary` step.
def reduce[A, I, F: Binary](
step: F,
var iterator: I,
*,
var initial: A,
) raises F.Error -> A where F.First == A and F.Second == _Source[I].Element and F.Out == A
Reduce with a library `Binary` step and no initial value.
def reduce[I, F: Binary](
step: F,
var iterator: I,
) raises _ReductionFailure[F.Error] -> F.Out where F.First == F.Out and F.Second == F.Out and _Source[I].Element == F.Out
reduce_optional¶
Source: fp/iteration/folds.mojo
def reduce_optional[T, I, //, F: def(var T, var T) -> T](
step: F,
var iterator: I,
) -> Optional[T] where _Source[I].Element == T
Reduce a source with its first element as the accumulator; empty input gives None.
Only empty input becomes absence. The step runs outside the boundary that
detects exhaustion, so a step that raises StopIteration fails as a step.
Parameters
T(Movable & Deinitable, inferred): The element and accumulator type.I(Movable & Deinitable, inferred): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.F(def(var T, var T) -> T): The step's type: a plain function or a closure.
Arguments
step(F): The step, borrowed; it is called once per element after the first.iterator(var I): The source, consumed.
Returns
Optional[T]: The final accumulator, or None for an empty source.
2 more overloads
Reduce with a raising step; empty input gives `None`, and the step's error is kept.
def reduce_optional[T, I, E: AnyType, //, F: def(var T, var T) raises E -> T](
step: F,
var iterator: I,
) raises E -> Optional[T] where _Source[I].Element == T
Reduce with a library `Binary` step; empty input gives `None`.
def reduce_optional[I, F: Binary](
step: F,
var iterator: I,
) raises F.Error -> Optional[F.Out] where F.First == F.Out and F.Second == F.Out and _Source[I].Element == F.Out
scan_left¶
Source: fp/iteration/adapters.mojo
def scan_left[A: Copyable & Deinitable, T, I](
function: def(var A, var T) thin -> A,
var initial: A,
var source: I,
) -> _Scan[A, T, _Source[I]] where _Source[I].Element == T
Lazily yield initial and then the accumulator after each step: n + 1 values for n elements.
The initial value is yielded before the first pull. Each yielded value is a
native copy of the accumulator, so retaining them costs their storage; a
shared-reference payload is not deep-cloned. For an eager scan with separate
carry and output values and no copies, use fp.control.scan.
Parameters
A(Copyable & Deinitable): The accumulator type, which must beCopyable.T(Movable & Deinitable): The element type.I(Movable & Deinitable): The source's type: a native iterator, or an owned collection (IterableOwned, such asList), which is consumed.
Arguments
function(def(var A, var T) thin -> A): A plain function(var A, var T) -> A, stored.initial(var A): The first accumulator, consumed.source(var I): The source, consumed.
Returns
A ScanIterator, a native iterator of the accumulator snapshots.
2 more overloads
Lazily yield the snapshots of a scan with a closure step.
def scan_left[A: Copyable & Deinitable, T, I, //, F: _LazyStep[A, T]](
var function: F,
var initial: A,
var source: I,
) -> _Scan[A, T, _Source[I], F] where _Source[I].Element == T
Lazily yield the snapshots of a scan with a library `Binary` step.
def scan_left[A: Copyable & Deinitable, I, F: Binary](
var function: F,
var initial: A,
var source: I,
) -> _Scan[A, F.Second, _Source[I], F] where F.First == A and F.Second == _Source[I].Element and F.Out == A and F.Error == Never
Structs¶
EmptyReductionError¶
Source: fp/iteration/folds.mojo
struct EmptyReductionError(Copyable, Movable, Writable)
The error of reduce without an initial value on an empty source.
Implements
Copyable, Writable
Iter¶
Source: fp/iteration/chaining.mojo
struct Iter[I: Iterator](Iterator, IterableOwned)
A native iterator with consuming transformation and terminal methods.
Start a chain with iterated(source). The wrapper stores only the native
iterator and preserves its current position and embedded origins. Methods
use the same implementations and contracts as the free functions.
Parameters
I(Iterator): The concrete native iterator type, including any borrowed origins.
Implements
IterableOwned, Iterator
Aliases
Element: The underlying iterator's element type.IteratorOwnedType: Consuming iteration keeps the same wrapper and its position.
Iter.all¶
def all[T, //, F: def(T) -> Bool](
deinit self,
predicate: F,
) -> Bool where I.Element == T
Stop at the first rejected element; empty input returns True.
The predicate borrows each candidate. A decisive result or predicate
error stops without another pull. Raising predicates preserve their error
type, and library BorrowCallable predicates are supported.
Parameters
T(Movable & Deinitable, inferred): The element type.F(def(T) -> Bool): The native predicate type.
Arguments
predicate(F): The predicate, borrowed.
Returns
Bool: True if every element is accepted, otherwise False.
2 more overloads
Test every element with a raising predicate, preserving its error.
def all[T, E, //, F: def(T) raises E -> Bool](
deinit self,
predicate: F,
) raises E -> Bool where I.Element == T
Test every element with a library borrowing predicate.
def all[C: BorrowCallable](
deinit self,
predicate: C,
) raises C.Failure -> Bool where conforms_to(I.Element, Movable & Deinitable) and C.Payload == I.Element and C.Result == Bool
Iter.any¶
def any[T, //, F: def(T) -> Bool](
deinit self,
predicate: F,
) -> Bool where I.Element == T
Stop at the first accepted element; empty input returns False.
The predicate borrows each candidate. A decisive result or predicate
error stops without another pull. Raising predicates preserve their error
type, and library BorrowCallable predicates are supported.
Parameters
T(Movable & Deinitable, inferred): The element type.F(def(T) -> Bool): The native predicate type.
Arguments
predicate(F): The predicate, borrowed.
Returns
Bool: True if any element is accepted, otherwise False.
2 more overloads
Test any element with a raising predicate, preserving its error.
def any[T, E, //, F: def(T) raises E -> Bool](
deinit self,
predicate: F,
) raises E -> Bool where I.Element == T
Test any element with a library borrowing predicate.
def any[C: BorrowCallable](
deinit self,
predicate: C,
) raises C.Failure -> Bool where conforms_to(I.Element, Movable & Deinitable) and C.Payload == I.Element and C.Result == Bool
Iter.bounds¶
def bounds(self) -> Tuple[Int, Optional[Int]]
Return the underlying iterator's remaining length bounds.
Returns
Tuple[Int, Optional[Int]]: The lower bound and optional upper bound, forwarded unchanged.
Iter.collect_list¶
def collect_list(
deinit self,
) -> List[Element] where conforms_to(Element, Deinitable)
Alias of to_list; consumes the remaining elements into a list.
Returns
List[Element]: A List[Element], with the same ownership and empty-input
behavior as to_list and the free collect_list.
Iter.filter¶
def filter[T](
deinit self,
predicate: def(T) thin -> Bool,
) -> Iter[FilterIterator[T, I]] where I.Element == T
Lazily retain the original elements a borrowing predicate accepts.
The predicate borrows each candidate. Rejected elements are destroyed;
accepted elements are moved out unchanged. Plain functions, closures and
non-raising BorrowCallable values are supported.
Parameters
T(Movable & Deinitable): The source element type.
Arguments
predicate(def(T) thin -> Bool): The non-raising predicate, stored.
Returns
Iter[FilterIterator[T, I]]: An Iter over accepted elements, in source order.
2 more overloads
Lazily retain elements with a stored closure predicate.
def filter[T, //, F: def(T) -> Bool](
deinit self,
var predicate: F,
) -> Iter[FilterIterator[T, I, F]] where I.Element == T
Lazily retain elements with a library borrowing predicate.
def filter[C: BorrowCallable](
deinit self,
var predicate: C,
) -> Iter[FilterIterator[I.Element, I, C]] where conforms_to(I.Element, Movable & Deinitable) and C.Payload == I.Element and C.Result == Bool and C.Failure == Never
Iter.filter_map¶
def filter_map[T, U](
deinit self,
function: def(var T) thin -> Optional[U],
) -> Iter[FilterMapIterator[T, U, I]] where I.Element == T
Lazily transform elements, yielding present values and skipping None.
Moves each element into the callback. Only absent Optional values are
skipped; a present Result.Err remains an ordinary element. Library
Unary callbacks name the result element parameter explicitly, U=U.
Parameters
T(Movable & Deinitable): The source element type.U(Movable & Deinitable): The element inside the returnedOptional.
Arguments
function(def(var T) thin -> Optional[U]): The non-raising callback returningOptional[U], stored.
Returns
Iter[FilterMapIterator[T, U, I]]: An Iter over present results.
2 more overloads
Lazily transform and filter elements with a stored closure.
def filter_map[T, U, //, F: def(var T) -> Optional[U]](
deinit self,
var function: F,
) -> Iter[FilterMapIterator[T, U, I, F]] where I.Element == T
Lazily filter a library `Unary` result; name `U` explicitly.
def filter_map[U, F: Unary](
deinit self,
var function: F,
) -> Iter[FilterMapIterator[F.Arg, U, I, F]] where I.Element == F.Arg and F.Out == Optional[U] and F.Error == Never
Iter.find¶
def find[T, //, F: def(T) -> Bool](
deinit self,
predicate: F,
) -> Optional[T] where I.Element == T
Consume through the first accepted element; no match returns None.
The predicate borrows each candidate. The first accepted original value
is returned without pulling another element. Raising predicates keep
their error type. Library BorrowCallable predicates are also accepted.
Parameters
T(Movable & Deinitable, inferred): The element type.F(def(T) -> Bool): The native predicate type.
Arguments
predicate(F): The predicate, borrowed.
Returns
Optional[T]: The first accepted element inside Optional, or None.
2 more overloads
Find with a raising predicate, propagating its exact error.
def find[T, E, //, F: def(T) raises E -> Bool](
deinit self,
predicate: F,
) raises E -> Optional[T] where I.Element == T
Find with a library borrowing predicate.
def find[C: BorrowCallable](
deinit self,
predicate: C,
) raises C.Failure -> Optional[I.Element] where conforms_to(I.Element, Movable & Deinitable) and C.Payload == I.Element and C.Result == Bool
Iter.flat_map¶
def flat_map[T, U](
deinit self,
function: def(var T) thin -> U,
) -> Iter[FlatMapIterator[T, U, I]] where I.Element == T
Lazily expand each element and exhaust its inner source in order.
Moves each element into the callback and retains the returned native
iterator or owned iterable until it is exhausted or abandoned. Empty inner
sources are skipped. A borrowed inner source retains its external origin.
Plain functions, closures and non-raising library Unary values are supported.
Parameters
T(Movable & Deinitable): The source element type.U(Movable & Deinitable): The inner iterator or owned iterable returned by the callback.
Arguments
function(def(var T) thin -> U): The non-raising callback, stored; move owned captures in with^.
Returns
Iter[FlatMapIterator[T, U, I]]: An Iter over the concatenated inner elements.
2 more overloads
Lazily expand each element with a stored closure.
def flat_map[T, U, //, F: def(var T) -> U](
deinit self,
var function: F,
) -> Iter[FlatMapIterator[T, U, I, F]] where I.Element == T
Lazily expand elements with a library `Unary` value.
def flat_map[F: Unary](
deinit self,
var function: F,
) -> Iter[FlatMapIterator[F.Arg, F.Out, I, F]] where I.Element == F.Arg and F.Error == Never
Iter.flatten¶
def flatten[S](deinit self) -> Iter[_Flatten[I, S]] where I.Element == S
Lazily concatenate inner sources, skipping empty ones.
Exhausts each inner iterator or owned iterable before pulling another outer element. Borrowed inner owners must remain alive and unmoved.
Parameters
S(Movable & Deinitable): The inner source type, inferred from this iterator's element type.
Returns
Iter[...]: An Iter over the concatenated inner elements.
Iter.fold_left¶
def fold_left[A, T, //, F: def(var A, var T) -> A](
deinit self,
step: F,
var initial: A,
) -> A where I.Element == T
Consume elements in order into an accumulator.
Empty input returns initial without calling the step. Steps are never
reassociated. The callback is borrowed and may be a plain function, a
closure or a library Binary value. Raising overloads propagate the
step's exact error type and stop without another pull.
Parameters
A(Movable & Deinitable, inferred): The accumulator type.T(Movable & Deinitable, inferred): The source element type.F(def(var A, var T) -> A): The native step type.
Arguments
step(F): The step, borrowed for the duration of the fold.initial(var A): The initial accumulator, consumed.
Returns
A: The final accumulator, moved out.
2 more overloads
Fold with a raising step, propagating its exact error type.
def fold_left[A, T, E: AnyType, //, F: def(var A, var T) raises E -> A](
deinit self,
step: F,
var initial: A,
) raises E -> A where I.Element == T
Fold with a library `Binary` step.
def fold_left[A, F: Binary](
deinit self,
step: F,
var initial: A,
) raises F.Error -> A where F.First == A and F.Second == I.Element and F.Out == A
Iter.fold_until¶
def fold_until[A, B, T, //, F: def(var A, var T) -> ControlFlow[B, A]](
deinit self,
step: F,
var initial: A,
) -> ControlFlow[B, A] where I.Element == T
Fold until Break, or return Continue with the final accumulator.
A break returns immediately without another pull. Empty input returns
Continue(initial). Raising overloads preserve the step's error as a
separate outcome from a Break. Library Binary steps are also accepted.
Parameters
A(Movable & Deinitable, inferred): The accumulator type.B(Movable & Deinitable, inferred): The break payload type.T(Movable & Deinitable, inferred): The source element type.F(def(var A, var T) -> ControlFlow[B, A]): The native step type.
Arguments
step(F): The step returningControlFlow[B, A], borrowed.initial(var A): The initial accumulator, consumed.
Returns
ControlFlow[B, A]: The first Break, or Continue with the final accumulator.
2 more overloads
Fold until `Break` with a raising step, preserving its error.
def fold_until[
A, B, T, E, //, F: def(var A, var T) raises E -> ControlFlow[B, A],
](
deinit self,
step: F,
var initial: A,
) raises E -> ControlFlow[B, A] where I.Element == T
Fold until `Break` with a library `Binary` step.
def fold_until[B, A, F: Binary](
deinit self,
step: F,
var initial: A,
) raises F.Error -> ControlFlow[B, A] where F.First == A and F.Second == I.Element and F.Out == ControlFlow[B, A]
Iter.map¶
def map[T, U](
deinit self,
function: def(var T) thin -> U,
) -> Iter[MapIterator[T, U, I]] where I.Element == T
Lazily transform each element and continue the chain.
Each element is moved into the stored callback. Construction pulls nothing.
Plain functions, capturing closures and non-raising library Unary values
use the same admission and execution as the free map.
Parameters
T(Movable & Deinitable): The source element type.U(Movable & Deinitable): The result element type.
Arguments
function(def(var T) thin -> U): The non-raising callback, stored; move owned captures in with^.
Returns
Iter[MapIterator[T, U, I]]: An Iter over the transformed elements.
2 more overloads
Lazily transform each element with a stored closure.
def map[T, U, //, F: def(var T) -> U](
deinit self,
var function: F,
) -> Iter[MapIterator[T, U, I, F]] where I.Element == T
Lazily transform each element with a library `Unary` value.
def map[F: Unary](
deinit self,
var function: F,
) -> Iter[MapIterator[F.Arg, F.Out, I, F]] where I.Element == F.Arg and F.Error == Never
Iter.reduce¶
def reduce[T, //, F: def(var T, var T) -> T](
deinit self,
step: F,
) raises EmptyReductionError -> T where I.Element == T
Reduce from the first element; empty input raises EmptyReductionError.
A non-empty input of length n calls the step n - 1 times. The overload
with initial= instead folds every element from that accumulator. Raising
uninitialized reductions distinguish empty input and step failure with
ReductionError[E]; initialized reductions propagate E directly.
Library Binary steps preserve the same contracts.
Parameters
T(Movable & Deinitable, inferred): The element and accumulator type.F(def(var T, var T) -> T): The native step type.
Arguments
step(F): The step, borrowed.
Returns
T: The reduced value, moved out.
Raises
EmptyReductionError: EmptyReductionError: The source is empty and no initializer was supplied.
5 more overloads
Reduce with a raising step, distinguishing step failure from empty input.
def reduce[T, E, //, F: def(var T, var T) raises E -> T](
deinit self,
step: F,
) raises ReductionError[E] -> T where I.Element == T
Reduce from the first element with a library `Binary` step.
def reduce[F: Binary](
deinit self,
step: F,
) raises _ReductionFailure[F.Error] -> F.Out where F.First == F.Out and F.Second == F.Out and I.Element == F.Out
Reduce from an explicit initial accumulator, as `fold_left` does.
def reduce[A, T, //, F: def(var A, var T) -> A](
deinit self,
step: F,
*,
var initial: A,
) -> A where I.Element == T
Reduce from an initial accumulator, preserving the step's error.
def reduce[A, T, E, //, F: def(var A, var T) raises E -> A](
deinit self,
step: F,
*,
var initial: A,
) raises E -> A where I.Element == T
Reduce from an initial accumulator with a library `Binary` step.
def reduce[A, F: Binary](
deinit self,
step: F,
*,
var initial: A,
) raises F.Error -> A where F.First == A and F.Second == I.Element and F.Out == A
Iter.reduce_optional¶
def reduce_optional[T, //, F: def(var T, var T) -> T](
deinit self,
step: F,
) -> Optional[T] where I.Element == T
Reduce from the first element, returning None for empty input.
Only empty input becomes absence. Raising overloads propagate the exact
step error, including StopIteration, and stop without another pull.
Library Binary steps are also accepted.
Parameters
T(Movable & Deinitable, inferred): The element and accumulator type.F(def(var T, var T) -> T): The native step type.
Arguments
step(F): The step, borrowed.
Returns
Optional[T]: The reduced value inside Optional, or None.
2 more overloads
Reduce with a raising step; only empty input becomes `None`.
def reduce_optional[T, E: AnyType, //, F: def(var T, var T) raises E -> T](
deinit self,
step: F,
) raises E -> Optional[T] where I.Element == T
Reduce with a library `Binary` step, returning `None` for empty input.
def reduce_optional[F: Binary](
deinit self,
step: F,
) raises F.Error -> Optional[F.Out] where F.First == F.Out and F.Second == F.Out and I.Element == F.Out
Iter.scan_left¶
def scan_left[A: Copyable & Deinitable, T](
deinit self,
step: def(var A, var T) thin -> A,
var initial: A,
) -> Iter[ScanIterator[A, T, I]] where I.Element == T
Lazily yield the initial accumulator and a copy after each step.
The first output copies initial without pulling an input. Each later
output applies the step once, then copies the accumulator. An input of
length n yields n + 1 snapshots. Closures and non-raising library
Binary steps retain the same contract as the free scan_left.
Parameters
A(Copyable & Deinitable): The copyable accumulator type.T(Movable & Deinitable): The source element type.
Arguments
step(def(var A, var T) thin -> A): The non-raising step, stored.initial(var A): The initial accumulator, consumed.
Returns
Iter[ScanIterator[A, T, I]]: An Iter over the accumulator snapshots.
2 more overloads
Lazily yield accumulator snapshots with a stored closure.
def scan_left[A: Copyable & Deinitable, T, //, F: def(var A, var T) -> A](
deinit self,
var step: F,
var initial: A,
) -> Iter[ScanIterator[A, T, I, F]] where I.Element == T
Lazily yield accumulator snapshots with a library `Binary` step.
def scan_left[A: Copyable & Deinitable, F: Binary](
deinit self,
var step: F,
var initial: A,
) -> Iter[ScanIterator[A, F.Second, I, F]] where F.First == A and F.Second == I.Element and F.Out == A and F.Error == Never
Iter.to_list¶
def to_list(deinit self) -> List[Element] where conforms_to(Element, Deinitable)
Consume the remaining elements into a list, in order.
Elements must be deinitializable, as for the free collect_list.
Each element moves into the result; no copy requirement is added.
Takes linear time and storage in the number of remaining elements.
Returns
List[Element]: A List[Element]; an empty list when the source is exhausted.
ReductionStepError¶
Source: fp/iteration/folds.mojo
struct ReductionStepError[E](Movable, Copyable where conforms_to(E, Copyable))
A reduction step's error, kept distinct from empty input.
A step that itself raises EmptyReductionError is still reported in this
alternative.
Parameters
E(Movable & Deinitable): The step's error type.
Implements
Copyable
Fields
error(E): The step's error, unchanged.
ReductionStepError.into_error¶
def into_error(deinit self) -> E
Consume the wrapper and return the step's error.
Returns
E: The step's error, moved out.
Aliases¶
FilterIterator¶
Source: fp/iteration/adapters.mojo
comptime FilterIterator[T, I: Iterator, F: Movable & Deinitable = def(T) thin -> Bool] = _Filter[T, I, F]
The type filter returns, for a generic function's return annotation.
Parameters
T(Movable & Deinitable): The element type.I(Iterator): The native iterator over the source.F(Movable & Deinitable): The predicate's type; the thin function type by default.
FilterMapIterator¶
Source: fp/iteration/adapters.mojo
comptime FilterMapIterator[T, U, I: Iterator, F: Movable & Deinitable = def(var T) thin -> Optional[U]] = _FilterMap[T, U, I, F]
The type filter_map returns, for a generic function's return annotation.
Parameters
T(Movable & Deinitable): The element type.U(Movable & Deinitable): The type of a present result.I(Iterator): The native iterator over the source.F(Movable & Deinitable): The function's type; the thin function type by default.
FlatMapIterator¶
Source: fp/iteration/adapters.mojo
comptime FlatMapIterator[T, U, I: Iterator, F: Movable & Deinitable = def(var T) thin -> U] = _Flatten[_Map[T, U, I, F], U]
The type flat_map returns, for a generic function's return annotation.
Parameters
T(Movable & Deinitable): The element type.U(Movable & Deinitable): The inner source the function returns, not the final element.I(Iterator): The native iterator over the source.F(Movable & Deinitable): The function's type; the thin function type by default.
MapIterator¶
Source: fp/iteration/adapters.mojo
comptime MapIterator[T, U, I: Iterator, F: Movable & Deinitable = def(var T) thin -> U] = _Map[T, U, I, F]
The type map returns, for a generic function's return annotation.
Parameters
T(Movable & Deinitable): The element type.U(Movable & Deinitable): The result type.I(Iterator): The native iterator over the source.F(Movable & Deinitable): The function's type; the thin function type by default.
ReductionError¶
Source: fp/iteration/folds.mojo
comptime ReductionError[E] = Variant[ EmptyReductionError, ReductionStepError[E] ]
The error of a raising reduce without an initial value: empty input, or the step's error.
A native Variant; check which alternative is active before taking it.
Parameters
E(Movable & Deinitable): The step's error type.
ScanIterator¶
Source: fp/iteration/adapters.mojo
comptime ScanIterator[A: Copyable & Deinitable, T, I: Iterator, F: Movable & Deinitable = def(var A, var T) thin -> A] = _Scan[A, T, I, F]
The type scan_left returns, for a generic function's return annotation.
Parameters
A(Copyable & Deinitable): The accumulator type.T(Movable & Deinitable): The element type.I(Iterator): The native iterator over the source.F(Movable & Deinitable): The step's type; the thin function type by default.
Fold scalars, SIMD vectors and documents with one function¶
"""The same sequential fold over scalar, SIMD and a user-defined document."""
from fp.iteration import fold_left
from std.iter import iter
from std.testing import assert_equal
def scalar(var total: Int, var value: Int) -> Int: return total + value
def vector[dtype: DType, width: Int](var total: SIMD[dtype, width],
var value: SIMD[dtype, width]) -> SIMD[dtype, width]:
return total + value
@fieldwise_init
struct Document(Movable):
var text: String
var words: Int
def append_word(var document: Document, var word: String) -> Document:
if document.words: document.text += " "
document.text += word
document.words += 1
return document^
def vectors[dtype: DType, width: Int]() raises:
comptime V = SIMD[dtype, width]
var first = V(0)
var second = V(0)
comptime for lane in range(width):
first[lane] = Scalar[dtype](lane + 1)
second[lane] = Scalar[dtype](10 + lane)
var inputs: List[V] = [first, second]
var expected = V(0)
for value in inputs: expected += value
var actual = fold_left(vector[dtype, width], V(0), iter(inputs))
comptime assert type_of(actual) == V
assert_equal(actual, expected)
assert_equal(actual.reduce_add(), Scalar[dtype](11 * width + width * (width - 1)))
assert_equal(fold_left(vector[dtype, width], first, List[V]()), first)
def main() raises:
var numbers: List[Int] = [1, 2, 3]
var expected = 0
for value in numbers: expected += value
assert_equal(fold_left(scalar, 0, iter(numbers)), expected)
assert_equal(fold_left(scalar, 7, List[Int]()), 7)
vectors[DType.int32, 4]()
vectors[DType.float64, 2]()
var words: List[String] = ["native", "functional", "composition"]
var native = Document(String(), 0)
for word in words: native = append_word(native^, word)
var document = fold_left(append_word, Document(String(), 0), words^)
assert_equal(document.text, native.text)
assert_equal(document.words, native.words)
var empty = fold_left(append_word, document^, List[String]())
assert_equal(empty.text, "native functional composition")
assert_equal(empty.words, 3)
print("scalar=", expected, "; document=", empty.text)
Run from the repository root pixi run mojo run -I src docs/examples/generic_fold.mojo
Output
scalar= 6 ; document= native functional composition
fold_left returns the accumulator type its step returns. Over [1, 2, 3]
with scalar it returns 6, and over an empty list it returns the initial
7. Over SIMD vectors, vector adds lane by lane and the result is still a
vector, equal to the hand-written loop; no lanes are reduced. Over three words,
append_word builds the Document "native functional composition" with a
word count of 3, the same as the loop in main.