baml.iter.Iterator

Implemented by types that produce a sequence of values, often from some container.

Reference version

Signature

interface baml.iter.Iterator

Implemented by types that produce a sequence of values, often from some container.

next is the only method without a default, so writing a new iterator means writing one method; everything else here is built from it. requires Iterable<...> makes every iterator iterable as itself, the same relationship Rust gets from its blanket IntoIterator for I: Iterator.

The adapters (map, filter, take, …) are lazy, like Rust's Iterator, Python's itertools, and JavaScript's iterator helpers: each returns a small class that holds the source and does no work — not even calling the function you passed it — until something calls next on it.

The consumers are what drive a chain, and so are where the source's errors surface. collect, reduce, count and for_each run it to exhaustion, and so never return on an infinite iterator; bound it with take first. some, every and find short circuit, and are safe on an infinite iterator so long as some element eventually settles the answer.

Adapters that take a function widen the error type: a chain's Error is the union of the source's and of every callback's, so one fallible step makes the whole chain fallible and says so in its type. Python and JavaScript track nothing of the sort — there a throwing callback simply propagates.

Source:<builtin>/baml/ns_iter/iter.bamlbytes 3664–19956

Associated types

type Item

type Error

= never

Required instance methods

function

next

(
self
) -> (Self as baml.iter.Iterator).Item | baml.iter.Done throws (Self as baml.iter.Iterator).Error

Advances the iterator and returns the next element, or baml.iter.Done once there are none left.

This is the one method an implementor must write; the rest of the interface is defined in terms of it.

Calling next again after it has returned Done is allowed. The leaf iterators here (ArrayIterator, Range, Repeat) and the adapters that latch (take, take_while) keep returning Done; the other adapters just ask their source again, so what happens is whatever the source does.

Throws

  • Self.Error if an error occurs while iterating. Depends on the implementation.

Default instance methods

function

chain

<E2>(
self,
other: baml.iter.Iterable<Error = E2, Item = (Self as baml.iter.Iterator).Item>
) -> baml.iter.Iterator<Error = (Self as baml.iter.Iterator).Error | E2, Item = (Self as baml.iter.Iterator).Item> throws never

Returns an iterator over all of self's elements followed by all of other's.

other.iter() is called right away, when the chain is built; only the advancing is deferred. The two sides may have different error types, and the result throws either.

Returns

A baml.iter.Chain.

function

collect

(self) -> (Self as baml.iter.Iterator).Item[] throws (Self as baml.iter.Iterator).Error

Consumes the rest of this iterator into an array, in order.

The rest: elements already pulled from a partly-consumed iterator are not included, and an already-exhausted iterator collects to [].

Throws

  • Self.Error if advancing the iterator fails. The elements gathered so far are lost, since the array is only returned on success.
function

count

(self) -> int throws (Self as baml.iter.Iterator).Error

Consumes the rest of this iterator and returns how many elements there were, 0 if it was already exhausted.

Every element is actually pulled — there is no size hint to short circuit with — so counting a chain runs the whole chain, callbacks included.

Throws

  • Self.Error if advancing the iterator fails.
function

every

<E2>(
self,
predicate: ((Self as baml.iter.Iterator).Item) -> bool throws E2
) -> bool throws (Self as baml.iter.Iterator).Error | E2

Whether predicate holds for every remaining element — Python's all, JavaScript's every.

Short circuits at the first false. An empty iterator gives true — the empty conjunction — which is worth remembering when the iterator may have been exhausted already.

Throws

  • Self.Error if advancing the iterator fails.
  • E2 if predicate throws.

ALIASES: all

function

filter

<E2>(
self,
predicate: ((Self as baml.iter.Iterator).Item) -> bool throws E2
) -> baml.iter.Iterator<Error = (Self as baml.iter.Iterator).Error | E2, Item = (Self as baml.iter.Iterator).Item> throws never

Returns an iterator over the elements for which predicate is true, in order.

A rejected element is skipped, not a stopping point — use baml.iter.Iterator.take_while to stop at the first failure instead.

Returns

A baml.iter.Filter yielding the kept elements.

function

filter_map

<R, E2>(
self,
fn: ((Self as baml.iter.Iterator).Item) -> R | null throws E2
) -> baml.iter.Iterator<Error = (Self as baml.iter.Iterator).Error | E2, Item = R> throws never

Returns an iterator over the non-null results of fn: map and filter in one pass.

null is the skip signal, so the produced item type R is the non-optional one. An iterator whose own items you want to keep as null cannot be expressed this way — filter and map it in two steps instead.

Returns

A baml.iter.FilterMap yielding the non-null results, in order.

function

find

<E2>(
self,
predicate: ((Self as baml.iter.Iterator).Item) -> bool throws E2
) -> (Self as baml.iter.Iterator).Item | null throws (Self as baml.iter.Iterator).Error | E2

The first remaining element for which predicate is true, or null if the iterator runs out first.

Short circuits: the matching element is consumed, and the iterator is left positioned just after it.

The result is Self.Item?, so — unlike next, which uses the distinct baml.iter.Done sentinel — an iterator whose items are themselves nullable cannot tell a found null from no match. Use baml.iter.Iterator.filter followed by next when that distinction matters.

Throws

  • Self.Error if advancing the iterator fails.
  • E2 if predicate throws.
function

flat_map

<R, E2, E3>(
self,
fn: ((Self as baml.iter.Iterator).Item) -> baml.iter.Iterable<Error = E3, Item = R> throws E2
) -> baml.iter.Iterator<Error = (Self as baml.iter.Iterator).Error | E2 | E3, Item = R> throws never

Returns an iterator over the elements of the iterables fn produces, laid end to end.

Each inner sequence is drained before the next outer element is pulled, and one that is empty contributes nothing. Three error types meet here — the source's, fn's E2, and the inner iterables' E3 — and the result throws all of them.

Returns

A baml.iter.FlatMap yielding R.

function

for_each

<E2>(
self,
fn: ((Self as baml.iter.Iterator).Item) -> null throws E2
) -> null throws (Self as baml.iter.Iterator).Error | E2

Calls fn on each remaining element, in order, for its side effects.

A for (.. in ..) loop is generally preferable; this is for the end of a long chain of calls. It runs to exhaustion — there is no way for fn to stop it early. Use baml.iter.Iterator.some or a for loop with a break when you need to.

Throws

  • Self.Error if advancing the iterator fails.
  • E2 if fn throws, which ends the traversal at that element.
function

map

<R, E2>(
self,
fn: ((Self as baml.iter.Iterator).Item) -> R throws E2
) -> baml.iter.Iterator<Error = (Self as baml.iter.Iterator).Error | E2, Item = R> throws never

Returns an iterator that applies fn to each element — Python's map, JavaScript's Iterator.prototype.map.

fn is applied exactly once per element that is actually pulled, in order, so a chain that ends early never touches the elements it skipped.

Returns

A baml.iter.Map yielding R, of the same length as self.

function

peekable

(
self
) -> baml.iter.Peekable<(Self as baml.iter.Iterator).Item, (Self as baml.iter.Iterator).Error> throws never

Returns an iterator with one element of look-ahead.

Unlike the other adapters this returns the concrete baml.iter.Peekable class rather than the Iterator interface, because peek lives on the class: an existential would hide it.

Returns

A baml.iter.Peekable yielding exactly what self yields, plus a peek that reads the next element without consuming it.

function

reduce

<A, E2>(
self,
fn: (A, (Self as baml.iter.Iterator).Item) -> A throws E2,
initial: A
) -> A throws (Self as baml.iter.Iterator).Error | E2

Folds every remaining element into an accumulator, left to right.

The accumulator starts at initial and each call to fn replaces it with the result; initial is what comes back for an empty iterator. Because the seed is required and its type A is independent of the item type, this is the operation Rust calls Iterator::fold and Python calls functools.reduce — not Rust's reduce.

Parameters

  • fn: combines the accumulator so far with the next element.
  • initial: the starting accumulator, and the result for an empty iterator.

Throws

  • Self.Error if advancing the iterator fails.
  • E2 if fn throws. The fold stops there; the partial accumulator is not recoverable.

ALIASES: fold

function

skip

(
self,
n: int
) -> baml.iter.Iterator<Error = (Self as baml.iter.Iterator).Error, Item = (Self as baml.iter.Iterator).Item> throws never

Returns an iterator over everything after the first n elements.

For n <= 0 every element is yielded; a source with fewer than n elements yields nothing. The skipped elements are pulled from the source and discarded — they are not free, and they can still throw. A skip is counted only once the source has actually yielded, so a throw the caller retries does not consume part of the count.

Parameters

  • n: how many leading elements to discard.

Returns

A baml.iter.Skip.

Examples

baml.iter.Range.new(0, 5).skip(2).collect() // [2, 3, 4]
function

skip_while

<E2>(
self,
predicate: ((Self as baml.iter.Iterator).Item) -> bool throws E2
) -> baml.iter.Iterator<Error = (Self as baml.iter.Iterator).Error | E2, Item = (Self as baml.iter.Iterator).Item> throws never

Returns an iterator over everything from the first element predicate rejects onwards.

That first rejected element is itself yielded — it is the start of the kept run, not a discarded boundary. The predicate is not consulted again afterwards, so later elements it would have matched are still yielded.

Returns

A baml.iter.SkipWhile.

Examples

// stops skipping at 3, so the trailing 1 and 2 are kept
[1, 2, 3, 1, 2].iter().skip_while((x: int) -> bool { x < 3 }).collect() // [3, 1, 2]
function

some

<E2>(
self,
predicate: ((Self as baml.iter.Iterator).Item) -> bool throws E2
) -> bool throws (Self as baml.iter.Iterator).Error | E2

Whether predicate holds for any remaining element — Python's any, JavaScript's some.

Short circuits at the first true, leaving the iterator positioned just after the matching element so it can be inspected further. An empty iterator gives false, the empty disjunction.

Throws

  • Self.Error if advancing the iterator fails.
  • E2 if predicate throws.

ALIASES: any

function

step_by

(
self,
n: int
) -> baml.iter.Iterator<Error = (Self as baml.iter.Iterator).Error, Item = (Self as baml.iter.Iterator).Item> throws never

Returns an iterator over every nth element, starting with the first.

The elements kept are those at positions 0, n, 2n, and so on. The skipped ones are still pulled from the source — and so may still throw — they are simply discarded.

Parameters

  • n: how far to advance between yielded elements. Values below 1 mean "advance by one", i.e. yield everything.

Returns

A baml.iter.StepBy.

function

take

(
self,
n: int
) -> baml.iter.Iterator<Error = (Self as baml.iter.Iterator).Error, Item = (Self as baml.iter.Iterator).Item> throws never

Returns an iterator over at most the first n elements.

Once n elements have been yielded the source is no longer advanced, and if the source ends first this ends with it. For n <= 0 it yields nothing. A slot is spent only once the source has actually yielded an element, so a source that throws and is then retried does not silently lose one.

This is the usual way to bound an unbounded iterator such as Repeat.new(v) or a wide Range.

Parameters

  • n: the greatest number of elements to yield.

Returns

A baml.iter.Take yielding at most n elements.

Examples

baml.iter.Repeat.new(0).take(5).collect()   // [0, 0, 0, 0, 0]
baml.iter.Range.new(0, 10).take(3).collect() // [0, 1, 2]
function

take_while

<E2>(
self,
predicate: ((Self as baml.iter.Iterator).Item) -> bool throws E2
) -> baml.iter.Iterator<Error = (Self as baml.iter.Iterator).Error | E2, Item = (Self as baml.iter.Iterator).Item> throws never

Returns an iterator over the leading run of elements for which predicate is true.

The element that fails the predicate is consumed from the source and is not yielded. Unlike filter, iteration stops at the first failure rather than skipping it, and the stop latches: the source is never advanced again, however often next is called.

Returns

A baml.iter.TakeWhile.

Examples

// stops at 5, so 6 and 8 are never yielded
[2, 4, 5, 6, 8].iter().take_while((x: int) -> bool { x % 2 == 0 }).collect() // [2, 4]