Class Subspace :: sus :: iter :: IteratorBase

template <class Iter, class ItemT>
class IteratorBase
{ ... };

The base class for all Iterator types.

The Iterator concept requires that a type subclasses from IteratorBase and is final in order to be considered an Iterator. No code should refer to IteratorBase except for defining the base class of an iterator, and it should be treated as an implementation detail only.

Methods

auto all(FnMut<bool(sus::iter::IteratorBase::Item)> auto f) -> bool

Tests whether all elements of the iterator match a predicate.

If the predicate returns true for all elements in the iterator, this functions returns true, otherwise false. The function is short-circuiting; it stops iterating on the first false returned from the predicate.

Returns true if the iterator is empty.

auto any(FnMut<bool(sus::iter::IteratorBase::Item)> auto f) -> bool

Tests whether any elements of the iterator match a predicate.

If the predicate returns true for any elements in the iterator, this functions returns true, otherwise false. The function is short-circuiting; it stops iterating on the first true returned from the predicate.

Returns false if the iterator is empty.

auto begin() & -> auto

Adaptor for use in ranged for loops.

auto by_ref() & -> Iterator<sus::iter::IteratorBase::Item> auto

Returns an iterator that refers to this iterator, and for which operations on it will also be applied to this iterator.

This is useful to allow applying iterator adapters while still retaining ownership of the original iterator.

template <class Other>
auto chain(Other&& other) && -> Iterator<sus::iter::IteratorBase::Item> auto
requires
sus::iter::IntoIterator<Other, ItemT>
template <class Other>
auto chain(Other&& other) && -> Iterator<Item> auto
requires
sus::iter::IntoIterator<Other, Item>

Takes two iterators and creates a new iterator over both in sequence.

chain() will return a new iterator which will first iterate over values from the first iterator and then over values from the second iterator.

In other words, it links two iterators together, in a chain. 🔗

sus::iter::Once is commonly used to adapt a single value into a chain of other kinds of iteration.

auto cloned() && -> Iterator<std::remove_cvref_t<sus::iter::IteratorBase::Item>> auto
requires
sus::mem::Clone<Item>

Creates an iterator which clones all of its elements.

This is useful when you have an iterator over T&, but you need an iterator over T.

There is no guarantee whatsoever about the clone method actually being called or optimized away. So code should not depend on either.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto cmp(Other&& other) && -> std::weak_ordering
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::Ord<ItemT, OtherItem>
template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto cmp(Other&& other) && -> std::weak_ordering
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::Ord<Item, OtherItem>

Lexicographically compares the elements of this Iterator with those of another.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto cmp_by(Other&& other, FnMut<std::weak_ordering(const std::remove_reference_t<sus::iter::IteratorBase::Item>&, const std::remove_reference_t<OtherItem>&)> auto cmp) && -> std::weak_ordering
requires
sus::iter::IntoIteratorAny<Other>

Lexicographically compares the elements of this Iterator with those of another with respect to the specified comparison function.

template <class C>
auto collect() && -> C
requires
sus::iter::FromIterator<C, ItemT>
template <class C>
auto collect() && -> C
requires
sus::iter::FromIterator<C, Item>

Transforms an iterator into a collection.

collect() can turn anything iterable into a relevant collection. If this is used anything like in Rust, it would be one of the more powerful methods in the subspace library, used in a variety of contexts.

The most basic pattern in which collect() is used is to turn one collection into another. You take a collection, call iter on it, do a bunch of transformations, and then collect() at the end.

collect() can also create instances of types that are not typical collections. For example, a string can be built from chars, and an iterator of Result<T, E> items can be collected into Result<Collection, E>. Or an iterator of Option can be collected into Option<Collection>.

Because collect() is so general, and C++ lacks strong type inference, collect() doesn't know the type of collection that you want to produce, so you will always need to pass it a type argument, such as:

sus::move(iter).collect<MyCollection<i32>>()
auto collect_vec() && -> sus::collections::Vec<ItemT>

Transforms an iterator into a Vec.

This function is a shorthand for it.collect<Vec<Item>>() in order to avoid the need for specifying a template argument.

See collect() for more details.

auto copied() && -> Iterator<std::remove_cvref_t<sus::iter::IteratorBase::Item>> auto
requires
sus::mem::Copy<Item>

Creates an iterator which copies all of its elements.

This is useful when you have an iterator over T&, but you need an iterator over T.

auto count() && -> usize

Consumes the iterator, and returns the number of elements that were in it.

The function walks the iterator until it sees an Option holding #None.

Panics

If the iterator has more than usize::MAX elements in it the usize will catch overflow and panic. To avoid panic, you may use a fold over OverflowInteger<usize> that increments the count each iteration.

auto cycle() && -> Iterator<sus::iter::IteratorBase::Item> auto
requires
sus::mem::Clone<Iter>

Repeats an iterator endlessly.

asdaa

Instead of stopping at None, the iterator will instead start again, from the beginning. After iterating again, it will start at the beginning again. And again. And again. Forever. Note that in case the original iterator is empty, the resulting iterator will also be empty.

The iterator must be Clone as it will be cloned in order to be repeatedly iterated.

auto end() & -> auto

Adaptor for use in ranged for loops.

auto enumerate() && -> auto

Creates an iterator which gives the current iteration count as well as the next value.

The iterator returned yields pairs (i, val), where i is the current index of iteration and val is the value returned by the iterator.

enumerate() keeps its count as a usize. If you want to count by a different sized integer, the zip() function provides similar functionality.

Overflow Behavior

The method does no guarding against overflows, so enumerating more than usize::MAX elements either produces the wrong result or panics depending on your build configuration. If debug assertions are enabled, a panic is guaranteed.

Panics

The returned iterator might panic if the to-be-returned index would overflow a usize.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto eq(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::Eq<ItemT, OtherItem>
template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto eq(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::Eq<Item, OtherItem>

Determines if the elements of this Iterator are equal to those of another.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto eq_by(Other&& other, FnMut<bool(const std::remove_reference_t<sus::iter::IteratorBase::Item>&, const std::remove_reference_t<OtherItem>&)> auto eq_fn) && -> bool
requires
sus::iter::IntoIteratorAny<Other>

Determines if the elements of this Iterator are equal to those of another with respect to the specified equality function.

auto filter(FnMut<bool(const std::remove_reference_t<sus::iter::IteratorBase::Item>&)> auto pred) && -> Iterator<sus::iter::IteratorBase::Item> auto

Creates an iterator which uses a closure to determine if an element should be yielded.

Given an element the closure must return true or false. The returned iterator will yield only the elements for which the closure returns true.

template <class MapFn, int &... , class R = std::invoke_result_t<MapFn &, ItemT &&>, class InnerR = typename ::sus::option::__private::IsOptionType<R>::inner_type>
auto filter_map(MapFn f) && -> Iterator<InnerR> auto
requires
sus::fn::FnMut<MapFn, ::sus::fn::NonVoid (ItemT &&)>
::sus::option::__private::IsOptionType<R>::value
template <class MapFn, int &... , class R = std::invoke_result_t<MapFn &, ItemT &&>, class InnerR = typename ::sus::option::__private::IsOptionType<R>::inner_type>
auto filter_map(MapFn f) && -> Iterator<InnerR> auto
requires
sus::fn::FnMut<MapFn, ::sus::fn::NonVoid (Item &&)>
::sus::option::__private::IsOptionType<R>::value
auto find(FnMut<bool(const std::remove_reference_t<sus::iter::IteratorBase::Item>&)> auto pred) -> Option<sus::iter::IteratorBase::Item>

Searches for an element of an iterator that satisfies a predicate.

find() takes a closure that returns true or false. It applies this predicate to each element of the iterator, and if any of them return true, then find() returns Some(element). If they all return false, it returns None.

find() is short-circuiting; in other words, it will stop processing as soon as the predicate returns true.

If you need the index of the element, see position().

template <class FindFn, int &... , class R = std::invoke_result_t<FindFn &, ItemT &&>, class InnerR = typename ::sus::option::__private::IsOptionType<R>::inner_type>
auto find_map(FindFn f) -> Option<InnerR>
requires
sus::fn::FnMut<FindFn, ::sus::fn::NonVoid (ItemT &&)>
::sus::option::__private::IsOptionType<R>::value
template <class FindFn, int &... , class R = std::invoke_result_t<FindFn &, ItemT &&>, class InnerR = typename ::sus::option::__private::IsOptionType<R>::inner_type>
auto find_map(FindFn f) -> Option<InnerR>
requires
sus::fn::FnMut<FindFn, ::sus::fn::NonVoid (Item &&)>
::sus::option::__private::IsOptionType<R>::value

Applies function to the elements of iterator and returns the first non-none result.

sus::move(iter).find_map(f) is equivalent to sus::move(iter).filter_map(f).next().

template <class F, int &... , class R = std::invoke_result_t<F &, ItemT &&>, class InnerR = typename IntoIteratorOutputType<R>::Item>
auto flat_map(F f) && -> Iterator<InnerR> auto
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (ItemT &&)>
sus::iter::IntoIteratorAny<R>
template <class F, int &... , class R = std::invoke_result_t<F &, ItemT &&>, class InnerR = typename IntoIteratorOutputType<R>::Item>
auto flat_map(F fn) && -> Iterator<InnerR> auto
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (Item &&)>
sus::iter::IntoIteratorAny<R>

Creates an iterator that works like map, but flattens nested structure.

The map() adapter is very useful, but only when the closure argument produces values. If it produces an iterator instead, there’s an extra layer of indirection. flat_map() will remove this extra layer on its own.

You can think of flat_map(f) as the semantic equivalent of mapping, and then flattening as in map(f).flatten().

Another way of thinking about flat_map(): map()'s closure returns one item for each element, and flat_map()'s closure returns an iterator for each element.

auto flatten() && -> auto
requires
sus::iter::IntoIteratorAny<Item>

Creates an iterator that flattens nested structure.

This is useful when you have an iterator of iterators or an iterator of things that can be turned into iterators and you want to remove one level of indirection.

In other words, this type maps Iterator[Iterable[T]] into Iterator[T].

template <class B, class F>
auto fold(B init, F f) && -> B
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (B, ItemT)>
std::convertible_to<std::invoke_result_t<F &, B &&, ItemT &&>, B>
!std::is_reference_v<B> ||
              std::is_reference_v<std::invoke_result_t<F&, B &&, ItemT &&>>
template <class B, class F>
auto fold(B init, F f) && -> B
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (B, Item)>
std::convertible_to<std::invoke_result_t<F &, B &&, Item &&>, B>
!std::is_reference_v<B> ||
            std::is_reference_v<std::invoke_result_t<F&, B &&, Item &&>>

Folds every element into an accumulator by applying an operation, returning the final result.

fold() takes two arguments: an initial value, and a closure with two arguments: an "accumulator", and an element. The closure returns the value that the accumulator should have for the next iteration.

The initial value is the value the accumulator will have on the first call.

After applying this closure to every element of the iterator, fold() returns the accumulator.

This operation is sometimes called "reduce" or "inject".

Folding is useful whenever you have a collection of something, and want to produce a single value from it.

Note: fold(), and similar methods that traverse the entire iterator, might not terminate for infinite iterators, even on traits for which a result is determinable in finite time.

Note: reduce() can be used to use the first element as the initial value, if the accumulator type and item type is the same.

Note: fold() combines elements in a left-associative fashion. For associative operators like +, the order the elements are combined in is not important, but for non-associative operators like - the order will affect the final result. For a right-associative version of fold(), see rfold() if the Iterator also satisfies DoubleEndedIterator.

Folding over References

The initial value type for fold will decay to a value (non-reference) by default, due to the way C++ templates resolve types. In order to fold over reference types, pass the type of the initial value explicitly as in the following example, which will return the last reference in the Iterator<i32&>.

auto v = sus::Vec<i32>(1, 2, 3);
i32 init;
i32& out = v.iter_mut().fold<i32&>(
    init, [](i32&, i32& v) -> i32& { return v; });
sus_check(&out == &v.last().unwrap());
template <class F>
auto for_each(F f) && -> void
requires
sus::fn::FnMut<F, void (ItemT &&)>
template <class F>
auto for_each(F f) && -> void
requires
sus::fn::FnMut<F, void (Item &&)>

Calls a closure on each element of an iterator.

This is equivalent to using a for loop on the iterator, although break and continue are not possible from a closure. It’s generally more idiomatic to use a for loop, but for_each may be more legible when processing items at the end of longer iterator chains. In some cases for_each may also be faster than a loop, because it avoids constructing a proxy type for the loop to consume.

auto fuse() && -> Iterator<sus::iter::IteratorBase::Item> auto

Creates an iterator which ends after the first None.

After an iterator returns None, future calls may or may not yield Some(T) again. fuse() adapts an iterator, ensuring that after a None is given, it will always return None forever.

This is useful for cases where the iterator may continue to be polled after it has returned None.

TODO: Implement a FusedIterator concept though a tag of some sort, so that fuse() can be a no-op in that case?

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto ge(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::PartialOrd<ItemT, OtherItem>
template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto ge(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::PartialOrd<Item, OtherItem>

Determines if the elements of this Iterator are lexicographically greater than or equal to those of another.

template <class GenFn, int &... , class R = std::invoke_result_t<GenFn &&, Iter &&>, class GenR = typename __private::IsGenerator<R>::type>
auto generate(GenFn generator_fn) && -> Iterator<GenR> auto
requires
sus::fn::FnOnce<GenFn, ::sus::fn::NonVoid (Iter &&)>
__private::IsGenerator<R>::value

Creates an iterator from a generator function that consumes the current iterator.

Coroutines can not be constexpr, so this function is not constexpr to avoid deeper compiler errors.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto gt(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::PartialOrd<ItemT, OtherItem>
template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto gt(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::PartialOrd<Item, OtherItem>

Determines if the elements of this Iterator are lexicographically greater than those of another.

auto inspect(FnMut<void(const std::remove_reference_t<sus::iter::IteratorBase::Item>&)> auto fn) && -> Iterator<sus::iter::IteratorBase::Item> auto

Does something with each element of an iterator, passing the value on.

When using iterators, you’ll often chain several of them together. While working on such code, you might want to check out what’s happening at various parts in the pipeline. To do that, insert a call to inspect().

It’s more common for inspect() to be used as a debugging tool than to exist in your final code, but applications may find it useful in certain situations when errors need to be logged before being discarded.

auto into_iter() && -> Iter&&

An Iterator also satisfies IntoIterator, which simply returns itself.

sus::iter::IntoIterator trait implementation.

auto is_sorted() -> bool
requires
sus::cmp::Ord<Item>

Checks if the elements of this iterator are sorted.

That is, it returns true if for each consecutive element a and b, a <= b is true. If the iterator yields exactly zero or one element, true is returned.

auto is_sorted_by(FnMut<std::weak_ordering(const std::remove_reference_t<sus::iter::IteratorBase::Item>&, const std::remove_reference_t<sus::iter::IteratorBase::Item>&)> auto compare) -> bool

Checks if the elements of this iterator are sorted using the given comparator function.

Returns true if for each consecutive element a and b, a <= b is true. If the iterator yields exactly zero or one element, true is returned.

auto last() && -> Option<sus::iter::IteratorBase::Item>

Consumes the iterator, returning the last element.

This method will evaluate the iterator until it returns None. While doing so, it keeps track of the current element. After None is returned, last() will then return the last element it saw.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto le(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::PartialOrd<ItemT, OtherItem>
template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto le(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::PartialOrd<Item, OtherItem>

Determines if the elements of this Iterator are lexicographically less than or equal to those of another.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto lt(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::PartialOrd<ItemT, OtherItem>
template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto lt(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::PartialOrd<Item, OtherItem>

Determines if the elements of this Iterator are lexicographically less than those of another.

template <class MapFn, int &... , class R = std::invoke_result_t<MapFn &, ItemT &&>>
auto map(MapFn fn) && -> Iterator<R> auto
requires
sus::fn::FnMut<MapFn, ::sus::fn::NonVoid (ItemT &&)>
template <class MapFn, int &... , class R = std::invoke_result_t<MapFn &, ItemT &&>>
auto map(MapFn fn) && -> Iterator<R> auto
requires
sus::fn::FnMut<MapFn, ::sus::fn::NonVoid (Item &&)>

Creates an iterator which uses a closure to map each element to another type.

The returned iterator's type is whatever is returned by the closure.

template <class MapFn, int &... , class R = std::invoke_result_t<MapFn &, ItemT &&>, class InnerR = typename ::sus::option::__private::IsOptionType<R>::inner_type>
auto map_while(MapFn fn) && -> Iterator<InnerR> auto
requires
sus::fn::FnMut<MapFn, ::sus::fn::NonVoid (ItemT &&)>
::sus::option::__private::IsOptionType<R>::value
template <class MapFn, int &... , class R = std::invoke_result_t<MapFn &, ItemT &&>, class InnerR = typename ::sus::option::__private::IsOptionType<R>::inner_type>
auto map_while(MapFn fn) && -> Iterator<InnerR> auto
requires
sus::fn::FnMut<MapFn, ::sus::fn::NonVoid (Item &&)>
::sus::option::__private::IsOptionType<R>::value

Creates an iterator that both yields elements based on a predicate and maps.

map_while() takes a closure as an argument that returns Options. It will call this closure on each element of the iterator, and yield elements while it returns an Option with a value in it.

auto max() && -> Option<sus::iter::IteratorBase::Item>
requires
sus::cmp::Ord<Item>

Returns the maximum element of an iterator.

If several elements are equally maximum, the last element is returned. If the iterator is empty, None is returned.

Note that f32/f64 doesn’t implement StrongOrd due to NaN being incomparable. You can work around this by using Iterator::reduce:

sus_check(
    sus::Array<f32, 3>(2.4, f32::NAN, 1.3)
        .into_iter()
        .reduce(&f32::max)
        .unwrap() ==
    2.4
);
auto max_by(FnMut<std::weak_ordering(const std::remove_reference_t<sus::iter::IteratorBase::Item>&, const std::remove_reference_t<sus::iter::IteratorBase::Item>&)> auto compare) && -> Option<sus::iter::IteratorBase::Item>

Returns the element that gives the maximum value with respect to the specified comparison function.

If several elements are equally maximum, the last element is returned. If the iterator is empty, None is returned.

template <class KeyFn, int &... , class Key = std::invoke_result_t<KeyFn &, const std::remove_reference_t<ItemT> &>>
auto max_by_key(KeyFn fn) && -> Option<sus::iter::IteratorBase::Item>
requires
sus::fn::FnMut<KeyFn, ::sus::fn::NonVoid (const std::remove_reference_t<ItemT> &)>
sus::cmp::Ord<Key>
!std::is_reference_v<Key>
template <class KeyFn, int &... , class Key = std::invoke_result_t<KeyFn &, const std::remove_reference_t<ItemT> &>>
auto max_by_key(KeyFn fn) && -> Option<Item>
requires
sus::fn::FnMut<KeyFn, ::sus::fn::NonVoid (const std::remove_reference_t<Item> &)>
sus::cmp::Ord<Key>
!std::is_reference_v<Key>

Returns the element that gives the maximum value from the specified function.

If several elements are equally maximum, the last element is returned. If the iterator is empty, None is returned.

auto min() && -> Option<sus::iter::IteratorBase::Item>
requires
sus::cmp::Ord<Item>

Returns the minimum element of an iterator.

If several elements are equally minimum, the first element is returned. If the iterator is empty, None is returned.

Note that f32/f64 doesn’t implement StrongOrd due to NaN being incomparable. You can work around this by using Iterator::reduce:

sus_check(
    sus::Array<f32, 3>(2.4, f32::NAN, 1.3)
        .into_iter()
        .reduce(&f32::min)
        .unwrap() ==
    2.4
);
auto min_by(FnMut<std::weak_ordering(const std::remove_reference_t<sus::iter::IteratorBase::Item>&, const std::remove_reference_t<sus::iter::IteratorBase::Item>&)> auto compare) && -> Option<sus::iter::IteratorBase::Item>

Returns the element that gives the minimum value with respect to the specified comparison function.

If several elements are equally minimum, the first element is returned. If the iterator is empty, None is returned.

template <class KeyFn, int &... , class Key = std::invoke_result_t<KeyFn &, const std::remove_reference_t<ItemT> &>>
auto min_by_key(KeyFn fn) && -> Option<sus::iter::IteratorBase::Item>
requires
sus::fn::FnMut<KeyFn, ::sus::fn::NonVoid (const std::remove_reference_t<ItemT> &)>
sus::cmp::Ord<Key>
!std::is_reference_v<Key>
template <class KeyFn, int &... , class Key = std::invoke_result_t<KeyFn &, const std::remove_reference_t<ItemT> &>>
auto min_by_key(KeyFn fn) && -> Option<Item>
requires
sus::fn::FnMut<KeyFn, ::sus::fn::NonVoid (const std::remove_reference_t<Item> &)>
sus::cmp::Ord<Key>
!std::is_reference_v<Key>

Returns the element that gives the minimum value from the specified function.

If several elements are equally minimum, the first element is returned. If the iterator is empty, None is returned.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto ne(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::Eq<ItemT, OtherItem>
template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto ne(Other&& other) && -> bool
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::Eq<Item, OtherItem>

Determines if the elements of this Iterator are not equal to those of another.

auto nth(sus::usize n) -> Option<sus::iter::IteratorBase::Item>

Returns the nth element of the iterator.

Like most indexing operations, the count starts from zero, so nth(0u) returns the first value, nth(1u) the second, and so on.

Note that all preceding elements, as well as the returned element, will be consumed from the iterator. That means that the preceding elements will be discarded, and also that calling nth(0u) multiple times on the same iterator will return different elements.

nth() will return None if n is greater than or equal to the length of the iterator. It will stop at the first None encountered in the iterator and return None.

auto nth_back(sus::usize n) -> Option<sus::iter::IteratorBase::Item>
requires
sus::iter::DoubleEndedIterator<Iter, Item>

Returns the nth element from the end of the iterator.

This is essentially the reversed version of Iterator::nth(). Although like most indexing operations, the count starts from zero, so nth_back(0) returns the first value from the end, nth_back(1) the second, and so on.

Note that all elements between the end and the returned element will be consumed, including the returned element. This also means that calling nth_back(0) multiple times on the same iterator will return different elements.

nth_back() will return None if n is greater than or equal to the length of the iterator. It will stop at the first None encountered in the iterator and return None.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto partial_cmp(Other&& other) && -> std::partial_ordering
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::PartialOrd<ItemT, OtherItem>
template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto partial_cmp(Other&& other) && -> std::partial_ordering
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::PartialOrd<Item, OtherItem>

Lexicographically compares the elements of this Iterator with those of another.

The comparison works like short-circuit evaluation, returning a result without comparing the remaining elements. As soon as an order can be determined, the evaluation stops and a result is returned.

For floating-point numbers, NaN does not have a total order and will result in std::partial_ordering::unordered when compared.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto partial_cmp_by(Other&& other, FnMut<std::partial_ordering(const std::remove_reference_t<sus::iter::IteratorBase::Item>&, const std::remove_reference_t<OtherItem>&)> auto cmp) && -> std::partial_ordering
requires
sus::iter::IntoIteratorAny<Other>

Lexicographically compares the elements of this Iterator with those of another with respect to the specified comparison function.

template <class B>
auto partition(FnMut<bool(const std::remove_reference_t<sus::iter::IteratorBase::Item>&)> auto pred) && -> Tuple<B, B>
requires
sus::construct::Default<B>
sus::iter::Extend<B, ItemT>
template <class B>
auto partition(FnMut<bool(const std::remove_reference_t<sus::iter::IteratorBase::Item>&)> auto pred) && -> Tuple<B, B>
requires
sus::construct::Default<B>
sus::iter::Extend<B, Item>

Consumes an iterator, creating two disjoint collections from it.

The predicate passed to partition() can return true or false. partition() returns a pair, all of the elements for which the predicate returned true, and all of the elements for which it returned false.

auto peekable() && -> Iterator<sus::iter::IteratorBase::Item> auto

Creates an iterator which can use the peek() and peek_mut() methods to look at the next element of the iterator without consuming it. See their documentation for more information.

A peekable iterator also supports conditionally pulling the next item out of the iterator, which is built on top of peek().

Note that the underlying iterator is still advanced when peek() or peek_mut() are called for the first time: In order to retrieve the next element, next() is called on the underlying iterator, hence any side effects (i.e. anything other than fetching the next value) of the next() method will occur.

auto position(FnMut<bool(sus::iter::IteratorBase::Item&&)> auto pred) -> Option<sus::usize>

Searches for an element in an iterator, returning its index.

position() takes a closure that returns true or false. It applies this closure to each element of the iterator, and if one of them returns true, then position() returns Some(index). If all of them return false, it returns None.

position() is short-circuiting; in other words, it will stop processing as soon as it finds a true.

If position is called multiple times on the same iterator, the second search starts where the first left off, but always considers the first element seen to be at position 0.

Panics

The method does no guarding against overflows, so if there are more than [usize::MAX] non-matching elements, it will panic.

template <class P = ItemT>
auto product() && -> P
requires
sus::iter::Product<P, ItemT>
template <class P = ItemT>
auto product() && -> P
requires
sus::iter::Product<P, Item>

Iterates over the entire iterator, multiplying all the elements.

An empty iterator returns the "one" value of the type.

product() can be used to multiply any type implementing Product, including numerics, Option and Result.

Panics

/ When calling product() and a primitive integer type is being returned, method will panic if the computation overflows.

Using product<OverflowInteger<T>>() will allow the caller to handle overflow without a panic.

auto range() && -> sus::iter::IteratorRange<Iter>

Converts the iterator into a std::ranges::range for use with the std ranges library.

This provides stdlib compatibility for iterators in libraries that expect stdlib types.

The sus/iter/compat_ranges.h header must be included separately to use this method, to avoid pulling in large stdlib headers by default.

template <class F, int &... , class R = std::invoke_result_t<F &, ItemT &&, ItemT &&>>
auto reduce(F f) && -> Option<sus::iter::IteratorBase::Item>
requires
sus::fn::FnMut<F, ItemT (ItemT, ItemT)>
!std::is_reference_v<ItemT> ||  //
             std::is_reference_v<R>
template <class F, int &... , class R = std::invoke_result_t<F &, ItemT &&, ItemT &&>>
auto reduce(F f) && -> Option<Item>
requires
sus::fn::FnMut<F, Item (Item, Item)>
!std::is_reference_v<Item> ||  //
           std::is_reference_v<R>

Reduces the elements to a single one, by repeatedly applying a reducing operation.

If the iterator is empty, returns None; otherwise, returns the result of the reduction.

The reducing function is a closure with two arguments: an 'accumulator', and an element. For iterators with at least one element, this is the same as fold() with the first element of the iterator as the initial accumulator value, folding every subsequent element into it.

Reducing References

If the iterator is over references, the reduce() function will be limited to returning a reference; in most cases to one of the members in the iterator.

To reduce and produce a new value, first apply .copied() or .cloned() and then reduce() that, such as it.copied().reduce(...) which will ensure the reduce() function is able to work with values instead of references.

This example uses copied() to copy each i32 and sum them.

auto a = sus::Array<i32, 3>(2, 3, 4);
auto out = a.iter().copied().reduce(
    [](i32 acc, i32 v) { return acc + v; });
sus_check(out.as_value() == 2 + 3 + 4);
auto rev() && -> Iterator<sus::iter::IteratorBase::Item> auto
requires
sus::iter::DoubleEndedIterator<Iter, Item>

Reverses an iterator's direction.

Usually, iterators iterate from front to back. After using rev(), an iterator will instead iterate from back to front.

This is only possible if the iterator has an end, so rev() only works on DoubleEndedIterators.

auto rfind(FnMut<bool(const std::remove_reference_t<sus::iter::IteratorBase::Item>&)> auto pred) -> Option<sus::iter::IteratorBase::Item>
requires
sus::iter::DoubleEndedIterator<Iter, Item>

Searches for an element of an iterator from the back that satisfies a predicate.

rfind() takes a closure that returns true or false. It applies this closure to each element of the iterator, starting at the end, and if any of them return true, then rfind() returns Some(element). If they all return false, it returns None.

rfind() is short-circuiting; in other words, it will stop processing as soon as the closure returns true.

template <class B, class F>
auto rfold(B init, F f) && -> B
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (B, ItemT)>
sus::iter::DoubleEndedIterator<Iter, ItemT>
std::convertible_to<std::invoke_result_t<F &, B &&, ItemT &&>, B>
!std::is_reference_v<B> ||
              std::is_reference_v<std::invoke_result_t<F&, B &&, ItemT &&>>
template <class B, class F>
auto rfold(B init, F f) && -> B
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (B, Item)>
sus::iter::DoubleEndedIterator<Iter, Item>
std::convertible_to<std::invoke_result_t<F &, B &&, Item &&>, B>
!std::is_reference_v<B> ||
            std::is_reference_v<std::invoke_result_t<F&, B &&, Item &&>>

An iterator method that reduces the iterator’s elements to a single, final value, starting from the back.

This is the reverse version of Iterator::fold(): it takes elements starting from the back of the iterator.

rfold() takes two arguments: an initial value, and a closure with two arguments: an "accumulator", and an element. The closure returns the value that the accumulator should have for the next iteration.

The initial value is the value the accumulator will have on the first call.

After applying this closure to every element of the iterator, rfold() returns the accumulator.

This operation is sometimes called "reduce" or "inject".

Folding is useful whenever you have a collection of something, and want to produce a single value from it.

Note: rfold() combines elements in a right-associative fashion. For associative operators like +, the order the elements are combined in is not important, but for non-associative operators like - the order will affect the final result. For a left-associative version of rfold(), see Iterator::fold().

auto rposition(FnMut<bool(sus::iter::IteratorBase::Item&&)> auto pred) -> Option<sus::usize>
requires
sus::iter::DoubleEndedIterator<Iter, Item>
sus::iter::ExactSizeIterator<Iter, Item>

Searches for an element in an iterator from the right, returning its index.

rposition() takes a closure that returns true or false. It applies this closure to each element of the iterator, starting from the end, and if one of them returns true, then rposition() returns Some(index). If all of them return false, it returns None.

rposition() is short-circuiting; in other words, it will stop processing as soon as it finds a true.

Because this requires the iterator to satisfy ExactSizeIterator, which means its length can be represented in a usize, this function can not overflow and will not panic.

template <class State, class F, int &... , class R = std::invoke_result_t<F &, State &, ItemT &&>, class InnerR = typename ::sus::option::__private::IsOptionType<R>::inner_type>
auto scan(State initial_state, F f) && -> Iterator<InnerR> auto
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (State &, ItemT &&)>
::sus::option::__private::IsOptionType<R>::value
!std::is_reference_v<State>
template <class State, class F, int &... , class R = std::invoke_result_t<F &, State &, ItemT &&>, class InnerR = typename ::sus::option::__private::IsOptionType<R>::inner_type>
auto scan(State initial_state, F f) && -> Iterator<InnerR> auto
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (State &, Item &&)>
::sus::option::__private::IsOptionType<R>::value
!std::is_reference_v<State>

An iterator adapter which, like fold(), holds internal state, but unlike fold(), produces a new iterator.

To write a function with internal state that receives the current iterator as input and yields items in arbitrary ways, see generate(). scan() is a less general tool where the given function is executed for each item in the iterator in order. However scan() is constexpr while generator coroutiunes can not be.

scan() takes two arguments: an initial value which seeds the internal state, and a closure with two arguments, the first being a mutable reference to the internal state and the second an iterator element. The closure can mutate the internal state to share state between iterations.

On iteration, the closure will be applied to each element of the iterator and the return value from the closure, an Option, is returned by the next method. Thus the closure can return Some(value) to yield value, or None to end the iteration.

auto skip(sus::usize n) && -> Iterator<sus::iter::IteratorBase::Item> auto

Creates an iterator that skips the first n elements.

skip(n) skips elements until n elements are skipped or the end of the iterator is reached (whichever happens first). After that, all the remaining elements are yielded. In particular, if the original iterator is too short, then the returned iterator is empty.

auto skip_while(FnMut<bool(const std::remove_reference_t<sus::iter::IteratorBase::Item>&)> auto pred) && -> Iterator<sus::iter::IteratorBase::Item> auto

Creates an iterator that skips elements based on a predicate.

skip_while() takes a closure as an argument. It will call this closure on each element of the iterator, and ignore elements until it returns false.

After false is returned, the closure is not called again, and the remaining elements are all yielded.

auto step_by(sus::usize step) && -> Iterator<sus::iter::IteratorBase::Item> auto

Creates an iterator starting at the same point, but stepping by the given amount at each iteration.

The first element of the iterator will always be returned, regardless of the step given. After that, skipped elements will be lazily walked over as needed.

step_by() behaves like the sequence next(), nth(step-1), self.nth(step-1), ...

Panics

The step must be greater than 0, or the function will panic. A step size of 1 returns every element.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto strong_cmp(Other&& other) && -> std::strong_ordering
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::StrongOrd<ItemT, OtherItem>
template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto strong_cmp(Other&& other) && -> std::strong_ordering
requires
sus::iter::IntoIteratorAny<Other>
sus::cmp::StrongOrd<Item, OtherItem>

Lexicographically compares the elements of this Iterator with those of another.

Strong ordering requires each item being compared that compares equal to share the same identity (be replaceable). Typically Ord is sufficient, which is required for cmp() and cmp_by(), where items that compare equivalent may still have different internal state.

The comparison works like short-circuit evaluation, returning a result without comparing the remaining elements. As soon as an order can be determined, the evaluation stops and a result is returned.

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto strong_cmp_by(Other&& other, FnMut<std::strong_ordering(const std::remove_reference_t<sus::iter::IteratorBase::Item>&, const std::remove_reference_t<OtherItem>&)> auto cmp) && -> std::strong_ordering
requires
sus::iter::IntoIteratorAny<Other>

Lexicographically compares the elements of this Iterator with those of another with respect to the specified comparison function.

template <class P = ItemT>
auto sum() && -> P
requires
sus::iter::Sum<P, ItemT>
template <class P = ItemT>
auto sum() && -> P
requires
sus::iter::Sum<P, Item>

Sums the elements of an iterator.

Takes each element, adds them together, and returns the result.

An empty iterator returns the zero value of the type.

sum() can be used to multiply any type implementing Sum, including numerics, Option and Result.

Panics

/ When calling sum() and a primitive integer type is being returned, method will panic if the computation overflows.

Using sum<OverflowInteger<T>>() will allow the caller to handle overflow without a panic.

auto take(sus::usize n) && -> Iterator<sus::iter::IteratorBase::Item> auto

Creates an iterator that yields the first n elements, or fewer if the underlying iterator ends sooner.

take(n) yields elements until n elements are yielded or the end of the iterator is reached (whichever happens first). The returned iterator is a prefix of length n if the original iterator contains at least n elements, otherwise it contains all of the (fewer than n) elements of the original iterator.

auto take_while(FnMut<bool(const std::remove_reference_t<sus::iter::IteratorBase::Item>&)> auto pred) && -> Iterator<sus::iter::IteratorBase::Item> auto

Creates an iterator that yields elements based on a predicate.

take_while() takes a closure as an argument. It will call this closure on each element of the iterator, and yield elements while it returns true.

After false is returned, the closure is not called again, and the remaining elements will not be yielded.

template <class C>
auto try_collect() -> auto
requires
sus::ops::Try<ItemT>
sus::iter::FromIterator<C, ::sus::ops::TryOutputType<ItemT>>
!std::is_void_v<::sus::ops::TryOutputType<ItemT>>
template <class C>
auto try_collect() -> auto
requires
sus::ops::Try<Item>
sus::iter::FromIterator<C, ::sus::ops::TryOutputType<Item>>
!std::is_void_v<::sus::ops::TryOutputType<Item>>

Fallibly transforms an iterator into a collection, short circuiting if a failure is encountered.

try_collect() is a variation of collect() that allows fallible conversions during collection. Its main use case is simplifying conversions from iterators yielding Option<T> into Option<Collection<T>>, or similarly for other Try types (e.g. Result or std::optional).

Importantly, try_collect() doesn’t require that the outer Try type also implements FromIterator; only the Try type's Output type must implement it. Concretely, this means that collecting into TryThing<Vec<i32>, _> can be valid because Vec<i32> implements FromIterator, even if TryThing doesn’t.

Also, if a failure is encountered during try_collect(), the iterator is still valid and may continue to be used, in which case it will continue iterating starting after the element that triggered the failure. See the last example below for an example of how this works.

Examples

Successfully collecting an iterator of Option<i32> into Option<Vec<i32>>:

auto u = Vec<Option<i32>>(some(1), some(2), some(3));
auto v = sus::move(u).into_iter().try_collect<Vec<i32>>();
sus_check(v == some(Vec<i32>(1, 2, 3 )));

Failing to collect in the same way:

auto u = Vec<Option<i32>>(some(1), some(2), none(), some(3));
auto v = sus::move(u).into_iter().try_collect<Vec<i32>>();
sus_check(v == none());

A similar example, but with Result:

enum Error { ERROR };
auto u = Vec<Result<i32, Error>>(ok(1), ok(2), ok(3));
auto v = sus::move(u).into_iter().try_collect<Vec<i32>>();
sus_check(v == ok(Vec<i32>(1, 2, 3)));
auto w = Vec<Result<i32, Error>>(ok(1), ok(2), err(ERROR), ok(3));
auto x = sus::move(w).into_iter().try_collect<Vec<i32>>();
sus_check(x == err(ERROR));
template <class B, class F, int &... , class R = std::invoke_result_t<F &, B &&, ItemT &&>>
auto try_fold(B init, F f) -> R
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (B, ItemT)>
sus::ops::Try<R>
std::convertible_to<typename ::sus::ops::TryImpl<R>::Output, B>
template <class B, class F, int &... , class R = std::invoke_result_t<F &, B &&, ItemT &&>>
auto try_fold(B init, F f) -> R
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (B, Item)>
sus::ops::Try<R>
std::convertible_to<typename ::sus::ops::TryImpl<R>::Output, B>

This function acts like fold() but the closure returns a type that satisfies sus::ops::Try and which converts to the accumulator type on success through the Try concept. If the closure ever returns failure, the fold operation immediately stops and returns the failure (short-circuiting).

See fold() for more on how to use this function.

Unlike fold() this function may be used on an iterator without fully consuming it, since it can stop iterating early.

Also unlike fold() the sus::ops::Try concept limits the accumulator value to not being a reference.

template <class F, int &... , class R = std::invoke_result_t<F &, ItemT &&>>
auto try_for_each(F f) -> R
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (ItemT)>
sus::ops::TryDefault<R>
template <class F, int &... , class R = std::invoke_result_t<F &, ItemT &&>>
auto try_for_each(F f) -> R
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (Item)>
sus::ops::TryDefault<R>

An iterator method that applies a fallible function to each item in the iterator, stopping at the first error and returning that error.

This can also be thought of as the fallible form of for_each() or as the stateless version of try_fold().

The closure must return a type that satisfies sus::ops::TryDefault. For each success value returned, the iteration will continue. When a failure is returned from the closure, iteration will stop and the failure will be returned from for_each(). On success, the default success value of the TryDefault is returned.

Unlike for_each() this function may be used on an iterator without fully consuming it, since it can stop iterating early.

template <class B, class F, int &... , class R = std::invoke_result_t<F &, B &&, ItemT &&>>
auto try_rfold(B init, F f) -> R
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (B, ItemT)>
sus::iter::DoubleEndedIterator<Iter, ItemT>
sus::ops::Try<R>
std::convertible_to<typename ::sus::ops::TryImpl<R>::Output, B>
template <class B, class F, int &... , class R = std::invoke_result_t<F &, B &&, ItemT &&>>
auto try_rfold(B init, F f) -> R
requires
sus::fn::FnMut<F, ::sus::fn::NonVoid (B, Item)>
sus::iter::DoubleEndedIterator<Iter, Item>
sus::ops::Try<R>
std::convertible_to<typename ::sus::ops::TryImpl<R>::Output, B>

This is the reverse version of Iterator::try_fold(): it takes elements starting from the back of the iterator.

template <class CollectionA, class CollectionB, int &... , class ItemA = typename ::sus::option::__private::IsTupleOfSizeTwo<ItemT>::first_type, class ItemB = typename ::sus::option::__private::IsTupleOfSizeTwo<ItemT>::second_type>
auto unzip() && -> Tuple<CollectionA, CollectionB>
requires
::sus::option::__private::IsTupleOfSizeTwo<ItemT>::value
sus::construct::Default<CollectionA>
sus::construct::Default<CollectionB>
sus::iter::Extend<CollectionA, ItemA>
sus::iter::Extend<CollectionB, ItemB>
template <class CollectionA, class CollectionB, int &... , class ItemA = typename ::sus::option::__private::IsTupleOfSizeTwo<ItemT>::first_type, class ItemB = typename ::sus::option::__private::IsTupleOfSizeTwo<ItemT>::second_type>
auto unzip() && -> Tuple<CollectionA, CollectionB>
requires
::sus::option::__private::IsTupleOfSizeTwo<Item>::value
sus::construct::Default<CollectionA>
sus::construct::Default<CollectionB>
sus::iter::Extend<CollectionA, ItemA>
sus::iter::Extend<CollectionB, ItemB>

Converts an iterator of pairs into a pair of collections.

unzip() consumes an entire iterator of pairs, producing two collections: one from the left elements of the pairs, and one from the right elements.

This function is, in some sense, the opposite of zip().

template <class Other, int &... , class OtherItem = typename IntoIteratorOutputType<Other>::Item>
auto zip(Other&& other) && -> Iterator<Tuple<ItemT, OtherItem>> auto
requires
sus::iter::IntoIteratorAny<Other>

"Zips up" two iterators into a single iterator of pairs.

zip() returns a new iterator that will iterate over two other iterators, returning a tuple where the first element comes from the first iterator, and the second element comes from the second iterator.

In other words, it zips two iterators together, into a single one.

If either iterator returns None, next() from the zipped iterator will return None. If the zipped iterator has returned None, further calls to next() will try advance both iterators, and if either returns None the zipped iterator will continue to return None. The zipped iterator is not fused if both iterators are not fused, and both resume returning values.

To "undo" the result of zipping up two iterators, see unzip.