iter

package
v1.5.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 11, 2023 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package iter is a package that provides a generic-type iterator.

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

nolint:unused

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func FindMap

func FindMap[T any, B any](iter Iterator[T], f func(T) gust.Option[B]) gust.Option[B]

FindMap applies function to the elements of data and returns the first non-none

`FindMap(iter, f)` is equivalent to `ToFilterMap(iter, f).Next()`.

Examples

var a = []string{"lol", "NaN", "2", "5"};

var first_number = FromVec(a).FindMap(func(s A) Option[any]{ return Wrap[any](strconv.Atoi(s))});

assert.Equal(t, first_number, gust.Some(2));

func Fold

func Fold[T any, B any](iter Iterator[T], init B, f func(B, T) B) B

Fold folds every element into an accumulator by applying an operation, returning the final

`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 data iteration.

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

After applying this closure to every element of the data, `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 data, might not terminate for infinite iterators, even on interfaces 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

Note to Implementors

Several of the other (forward) methods have default implementations in terms of this one, so try to implement this explicitly if it can do something better than the default `for` loop implementation.

In particular, try to have this call `Fold()` on the internal parts from which this data is composed.

Examples

Basic usage:

var a = []int{1, 2, 3};

the sum of iAll the elements of the array var sum = FromVec(a).Fold((0, func(acc int, x int) any { return acc + x });

assert.Equal(t, sum, 6);

Let's walk through each step of the iteration here:

| element | acc | x | result | |---------|-----|---|--------| | | 0 | | | | 1 | 0 | 1 | 1 | | 2 | 1 | 2 | 3 | | 3 | 3 | 3 | 6 |

And so, our final result, `6`.

func Rfold

func Rfold[T any, B any](iter DeIterator[T], init B, f func(B, T) B) B

Rfold is an iterator method that reduces the iterator elements to a single, final value, starting from the back.

func SigTryFold added in v1.0.0

func SigTryFold[T any, CB any](iter Iterator[T], init CB, f func(CB, T) gust.SigCtrlFlow[CB]) gust.SigCtrlFlow[CB]

SigTryFold a data method that applies a function as long as it returns successfully, producing a single, final value.

assert.Equal(t, sum, Ok(6));

func TryFold

func TryFold[T any, B any, C any](iter Iterator[T], init C, f func(C, T) gust.CtrlFlow[B, C]) gust.CtrlFlow[B, C]

TryFold a data method that applies a function as long as it returns successfully, producing a single, final value.

func TryRfold

func TryRfold[T any, CB any](iter DeIterator[T], init CB, f func(CB, T) gust.SigCtrlFlow[CB]) gust.SigCtrlFlow[CB]

TryRfold is the reverse version of [`Iterator[T].TryFold()`]: it takes elements starting from the back of the iterator.

Types

type DeIterator

type DeIterator[T any] interface {
	Iterator[T]

	// Rposition 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`.
	Rposition(predicate func(T) bool) gust.Option[int]
	// ToDeFuse creates a double ended iterator which ends after the first [`gust.None[T]()`].
	//
	// After an iterator returns [`gust.None[T]()`], future calls may or may not yield
	// [`gust.Some(T)`] again. `ToFuse()` adapts an iterator, ensuring that after a
	// [`gust.None[T]()`] is given, it will always return [`gust.None[T]()`] forever.
	ToDeFuse() DeIterator[T]
	// ToDePeekable creates a double ended iterator which can peek at the next element.
	ToDePeekable() DePeekableIterator[T]
	// ToDeSkip creates a double ended iterator that skips the first `n` elements.
	//
	// `ToDeSkip(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.
	//
	// Rather than overriding this method directly, instead override the `Nth` method.
	ToDeSkip(n uint) DeIterator[T]
	// ToDeTake creates an iterator that yields the first `n` elements, or fewer
	// if the underlying iterator ends sooner.
	//
	// `ToDeTake(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 the
	// (fewer than `n`) elements of the original iterator.
	ToDeTake(n uint) DeIterator[T]
	// ToDeChain takes two iterators and creates a new data over both in sequence.
	//
	// `ToDeChain()` will return a new data which will first iterate over
	// values from the first data and then over values from the second
	// data.
	//
	// In other words, it links two iterators together, in a chain. 🔗
	//
	// # Examples
	//
	// Basic usage:
	//
	//
	// var a1 = []int{1, 2, 3};
	// var a2 = []int{4, 5, 6};
	//
	// var iter = FromVec(a1).ToChain(FromVec(a2));
	//
	// assert.Equal(t, iter.Next(), gust.Some(1));
	// assert.Equal(t, iter.Next(), gust.Some(2));
	// assert.Equal(t, iter.Next(), gust.Some(3));
	// assert.Equal(t, iter.Next(), gust.Some(4));
	// assert.Equal(t, iter.Next(), gust.Some(5));
	// assert.Equal(t, iter.Next(), gust.Some(6));
	// assert.Equal(t, iter.Next(), gust.None[int]());
	//
	ToDeChain(other DeIterator[T]) DeIterator[T]
	// ToDeFilter creates a double ended 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.
	//
	// # Examples
	//
	// Basic usage:
	//
	// “`
	// var a = []int{0, 1, 2};
	//
	// var iter = FromVec(a).ToFilter(func(x int)bool{return x>0});
	//
	// assert.Equal(iter.Next(), gust.Some(&1));
	// assert.Equal(iter.Next(), gust.Some(&2));
	// assert.Equal(iter.Next(), gust.None[int]());
	// “`
	//
	// Note that `iter.ToDeFilter(f).Next()` is equivalent to `iter.Find(f)`.
	ToDeFilter(f func(T) bool) DeIterator[T]
	// ToDeFilterMap creates a double ended iterator that both filters and maps.
	//
	// The returned iterator yields only the `value`s for which the supplied
	// closure returns `gust.Some(value)`.
	//
	// `ToFilterMap` can be used to make chains of [`ToFilter`] and [`ToMap`] more
	// concise. The example below shows how a `ToMap().ToFilter().ToMap()` can be
	// shortened to a single call to `ToFilterMap`.
	//
	// # Examples
	//
	// Basic usage:
	//
	// “`
	// var a = []string{"1", "two", "NaN", "four", "5"}
	//
	// var iter = FromVec(a).ToDeFilterMap(|s| s.parse().ok());
	//
	// assert.Equal(iter.Next(), gust.Some(1));
	// assert.Equal(iter.Next(), gust.Some(5));
	// assert.Equal(iter.Next(), gust.None[string]());
	// “`
	ToDeFilterMap(f func(T) gust.Option[T]) DeIterator[T]
	// ToXDeFilterMap creates an iterator that both filters and maps.
	ToXDeFilterMap(f func(T) gust.Option[any]) DeIterator[any]
	// ToDeInspect takes a closure and executes it with each element.
	ToDeInspect(f func(T)) DeIterator[T]
	// ToDeMap takes a closure and creates a double ended iterator which calls that closure on each
	// element.
	//
	// If you are good at thinking in types, you can think of `ToDeMap()` like this:
	// If you have an iterator that gives you elements of some type `A`, and
	// you want an iterator of some other type `B`, you can use `ToDeMap()`,
	// passing a closure that takes an `A` and returns a `B`.
	//
	// `ToDeMap()` is conceptually similar to a [`for`] loop. However, as `ToDeMap()` is
	// lazy, it is best used when you're already working with other iterators.
	// If you're doing some sort of looping for a side effect, it's considered
	// more idiomatic to use [`for`] than `ToDeMap()`.
	//
	// # Examples
	//
	// Basic usage:
	//
	// “`
	// var a = []int{1, 2, 3};
	//
	// var iter = FromVec(a).ToDeMap(func(x)int{ return 2 * x});
	//
	// assert.Equal(iter.Next(), gust.Some(2));
	// assert.Equal(iter.Next(), gust.Some(4));
	// assert.Equal(iter.Next(), gust.Some(6));
	// assert.Equal(iter.Next(), gust.None[int]());
	// “`
	//
	ToDeMap(f func(T) T) DeIterator[T]
	// ToXDeMap takes a closure and creates an iterator which calls that closure on each
	// element.
	ToXDeMap(f func(T) any) DeIterator[any]
	// ToRev reverses an iterator's direction.
	//
	// Usually, iterators iterate from left to right. After using `ToRev()`,
	// an iterator will instead iterate from right to left.
	ToRev() DeIterator[T]
	// contains filtered or unexported methods
}

DeIterator is an iterator able to yield elements from both ends.

func EnumDeIterable

func EnumDeIterable[T any](data gust.DeIterable[T]) DeIterator[gust.VecEntry[T]]

EnumDeIterable creates a double ended iterator with index from an Iterable.

func EnumElements

func EnumElements[T any](elems ...T) DeIterator[gust.VecEntry[T]]

EnumElements creates a double ended iterator with index from a set of elements.

func EnumOption

func EnumOption[T any](opt gust.Option[T]) DeIterator[gust.VecEntry[T]]

EnumOption creates a double ended iterator with index from an option.

func EnumRange

func EnumRange[T gust.Integer](start T, end T, rightClosed ...bool) DeIterator[gust.VecEntry[T]]

EnumRange creates a double ended iterator with index from a range.

func EnumResult

func EnumResult[T any](ret gust.Result[T]) DeIterator[gust.VecEntry[T]]

EnumResult creates a double ended iterator with index from a result.

func EnumString

func EnumString[T ~byte | ~rune](s string) DeIterator[gust.VecEntry[T]]

EnumString creates a double ended iterator with index from a string.

func EnumVec

func EnumVec[T any](slice []T) DeIterator[gust.VecEntry[T]]

EnumVec creates a double ended iterator with index from a slice.

func FromDeIterable

func FromDeIterable[T any](data gust.DeIterable[T]) DeIterator[T]

FromDeIterable creates a double ended iterator from an Iterable.

func FromElements

func FromElements[T any](elems ...T) DeIterator[T]

FromElements creates a double ended iterator from a set of elements.

func FromOption

func FromOption[T any](opt gust.Option[T]) DeIterator[T]

FromOption creates a double ended iterator from an option.

func FromRange

func FromRange[T gust.Integer](start T, end T, rightClosed ...bool) DeIterator[T]

FromRange creates a double ended iterator from a range.

func FromResult

func FromResult[T any](ret gust.Result[T]) DeIterator[T]

FromResult creates a double ended iterator from a result.

func FromString

func FromString[T ~byte | ~rune](s string) DeIterator[T]

FromString creates a double ended iterator from a string.

func FromVec

func FromVec[T any](slice []T) DeIterator[T]

FromVec creates a double ended iterator from a slice.

func ToDeEnumerate added in v1.0.0

func ToDeEnumerate[T any](iter DeIterator[T]) DeIterator[gust.VecEntry[T]]

ToDeEnumerate creates a double ended iterator that yields pairs of the index and the value.

func ToDeFilterMap added in v1.0.0

func ToDeFilterMap[T any, B any](iter DeIterator[T], f func(T) gust.Option[B]) DeIterator[B]

ToDeFilterMap creates a double ended iterator that both filters and maps.

The returned iterator yields only the `value`s for which the supplied closure returns `gust.Some(value)`.

func ToDeFlatMap added in v1.0.0

func ToDeFlatMap[T any, B any](iter DeIterator[T], f func(T) DeIterator[B]) DeIterator[B]

ToDeFlatMap creates a double ended iterator that works like map, but flattens nested structure.

The [`ToDeMap`] 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. `ToDeFlatMap()` will remove this extra layer on its own.

You can think of `ToDeFlatMap(f)` as the semantic equivalent of [`ToDeMap`]ping, and then [`ToDeFlatten`]ing as in `ToDeFlatten(ToDeMap(f))`.

Another way of thinking about `ToDeFlatMap()`: [`ToDeMap`]'s closure returns one item for each element, and `ToDeFlatMap()`'s closure returns an iterator for each element.

func ToDeFlatten added in v1.0.0

func ToDeFlatten[I gust.DeIterable[T], T any](iter DeIterator[I]) DeIterator[T]

ToDeFlatten creates a double ended iterator that flattens nested structure.

func ToDeMap added in v1.0.0

func ToDeMap[T any, B any](iter DeIterator[T], f func(T) B) DeIterator[B]

ToDeMap takes a closure and creates a double ended iterator which calls that closure on each element.

If you are good at thinking in types, you can think of `ToDeMap()` like this: If you have an iterator that gives you elements of some type `A`, and you want an iterator of some other type `B`, you can use `ToDeMap()`, passing a closure that takes an `A` and returns a `B`.

`ToDeMap()` is conceptually similar to a [`for`] loop. However, as `ToDeMap()` is lazy, it is best used when you're already working with other iterators. If you're doing some sort of looping for a side effect, it's considered more idiomatic to use [`for`] than `ToDeMap()`.

func ToDeUnique added in v1.2.2

func ToDeUnique[T comparable](iter DeIterator[T]) DeIterator[T]

ToDeUnique return a double ended iterator adaptor that filters out elements that have already been produced once during the iteration. Duplicates are detected using hash and equality.

Clones of visited elements are stored in a hash set in the iterator.

The iterator is stable, returning the non-duplicate items in the order in which they occur in the adapted iterator. In a set of duplicate items, the first item encountered is the item retained.

``` var data = FromElements(10, 20, 30, 20, 40, 10, 50); ToDeUnique(data).Collect() // [10, 20, 30, 40, 50] ```

func ToDeUniqueBy added in v1.2.2

func ToDeUniqueBy[T any, K comparable](iter DeIterator[T], f func(T) K) DeIterator[T]

ToDeUniqueBy return an iterator adaptor that filters out elements that have already been produced once during the iteration.

Duplicates are detected by comparing the key they map to with the keying function `f` by hash and equality. The keys are stored in a hash set in the iterator.

The iterator is stable, returning the non-duplicate items in the order in which they occur in the adapted iterator. In a set of duplicate items, the first item encountered is the item retained.

``` var data = FromElements("a", "bb", "aa", "c", "ccc"); ToDeUniqueBy(data, func(s string)int {return len(s)}).Collect() // "a", "bb", "ccc" ```

func ToDeZip added in v1.0.0

func ToDeZip[A any, B any](a DeIterator[A], b DeIterator[B]) DeIterator[gust.Pair[A, B]]

ToDeZip is similar to `ToZip`, but it supports take elements starting from the back of the iterator.

type DePeekableIterator

type DePeekableIterator[T any] interface {
	DeIterator[T]
	// contains filtered or unexported methods
}

type IterableChan

type IterableChan[T any] struct {
	// contains filtered or unexported fields
}

func NewIterableChan

func NewIterableChan[T any](c chan T) IterableChan[T]

func (IterableChan[T]) Count

func (c IterableChan[T]) Count() uint

func (IterableChan[T]) Next

func (c IterableChan[T]) Next() gust.Option[T]

func (IterableChan[T]) SizeHint

func (c IterableChan[T]) SizeHint() (uint, gust.Option[uint])

func (IterableChan[T]) ToIterator

func (c IterableChan[T]) ToIterator() Iterator[T]

type IterableRange

type IterableRange[T gust.Integer] struct {
	// contains filtered or unexported fields
}

func NewIterableRange

func NewIterableRange[T gust.Integer](start T, end T, rightClosed ...bool) *IterableRange[T]

func (*IterableRange[T]) Count

func (r *IterableRange[T]) Count() uint

func (*IterableRange[T]) Next

func (r *IterableRange[T]) Next() gust.Option[T]

func (*IterableRange[T]) NextBack

func (r *IterableRange[T]) NextBack() gust.Option[T]

func (*IterableRange[T]) Remaining

func (r *IterableRange[T]) Remaining() uint

func (*IterableRange[T]) SizeHint

func (r *IterableRange[T]) SizeHint() (uint, gust.Option[uint])

func (*IterableRange[T]) ToDeIterator

func (r *IterableRange[T]) ToDeIterator() DeIterator[T]

type IterableVec

type IterableVec[T any] struct {
	// contains filtered or unexported fields
}

func NewIterableVec

func NewIterableVec[T any](slice []T) *IterableVec[T]

func (*IterableVec[T]) Count

func (v *IterableVec[T]) Count() uint

func (*IterableVec[T]) Next

func (v *IterableVec[T]) Next() gust.Option[T]

func (*IterableVec[T]) NextBack

func (v *IterableVec[T]) NextBack() gust.Option[T]

func (*IterableVec[T]) Remaining

func (v *IterableVec[T]) Remaining() uint

func (*IterableVec[T]) SizeHint

func (v *IterableVec[T]) SizeHint() (uint, gust.Option[uint])

func (*IterableVec[T]) ToDeIterator

func (v *IterableVec[T]) ToDeIterator() DeIterator[T]

type Iterator

type Iterator[T any] interface {
	// Collect collects all the items in the iterator into a slice.
	Collect() []T
	// Next advances the data and returns the data value.
	//
	// Returns [`gust.None[T]()`] when iteration is finished. Individual data
	// implementations may choose to resume iteration, and so calling `data()`
	// again may or may not eventually min returning [`gust.Some(A)`] again at some
	// point.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3};
	//
	// var iter = FromVec(a);
	//
	// A call to data() returns the data value...
	// assert.Equal(t, gust.Some(1), iter.Next());
	// assert.Equal(t, gust.Some(2), iter.Next());
	// assert.Equal(t, gust.Some(3), iter.Next());
	//
	// ... and then None once it's over.
	// assert.Equal(t, gust.None[int](), iter.Next());
	//
	// More calls may or may not return `gust.None[T]()`. Here, they always will.
	// assert.Equal(t, gust.None[int](), iter.Next());
	// assert.Equal(t, gust.None[int](), iter.Next());
	Next() gust.Option[T]
	// NextChunk advances the iterator and returns an array containing the data `n` values, then `true` is returned.
	//
	// If there are not enough elements to fill the array then `false` is returned
	// containing an iterator over the remaining elements.
	NextChunk(n uint) gust.EnumResult[[]T, []T]
	// SizeHint returns the bounds on the remaining length of the data.
	//
	// Specifically, `SizeHint()` returns a tuple where the first element
	// is the lower bound, and the second element is the upper bound.
	//
	// The second half of the tuple that is returned is an `Option[A]`.
	// A [`gust.None[T]()`] here means that either there is no known upper bound, or the
	// upper bound is larger than [`int`].
	//
	// # Implementation notes
	//
	// It is not enforced that a data implementation yields the declared
	// number of elements. A buggy data may yield less than the lower bound
	// or more than the upper bound of elements.
	//
	// `SizeHint()` is primarily intended to be used for optimizations such as
	// reserving space for the elements of the data, but must not be
	// trusted to e.g., omit bounds checks in unsafe code. An incorrect
	// implementation of `SizeHint()` should not lead to memory safety
	// violations.
	//
	// That said, the implementation should provide a correct estimation,
	// because otherwise it would be a violation of the interface's protocol.
	//
	// The default implementation returns `(0, [None[int]()])` which is correct for any
	// data.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3};
	// var iter = FromVec(a);
	//
	// assert.Equal(t, (3, gust.Some(3)), iter.SizeHint());
	//
	// A more complex example:
	//
	// The even numbers in the range of zero to nine.
	// var iter = FromRange(0..10).ToFilter(func(x A) {return x % 2 == 0});
	//
	// We might iterate from zero to ten times. Knowing that it's five
	// exactly wouldn't be possible without executing filter().
	// assert.Equal(t, (0, gust.Some(10)), iter.SizeHint());
	//
	// Let's add five more numbers with chain()
	// var iter = FromRange(0, 10).ToFilter(func(x A) {return x % 2 == 0}).ToChain(FromRange(15, 20));
	//
	// now both bounds are increased by five
	// assert.Equal(t, (5, gust.Some(15)), iter.SizeHint());
	//
	// Returning `gust.None[int]()` for an upper bound:
	//
	// an infinite data has no upper bound
	// and the maximum possible lower bound
	// var iter = FromRange(0, math.MaxInt);
	//
	// assert.Equal(t, (math.MaxInt, gust.None[int]()), iter.SizeHint());
	SizeHint() (uint, gust.Option[uint])
	// Count consumes the data, counting the number of iterations and returning it.
	//
	// This method will call [`Next`] repeatedly until [`gust.None[T]()`] is encountered,
	// returning the number of times it saw [`gust.Some`]. Note that [`Next`] has to be
	// called at least once even if the data does not have any elements.
	//
	// # Overflow Behavior
	//
	// The method does no guarding against overflows, so counting elements of
	// a data with more than [`math.MaxInt`] elements either produces the
	// wrong result or panics. If debug assertions are enabled, a panic is
	// guaranteed.
	//
	// # Panics
	//
	// This function might panic if the data has more than [`math.MaxInt`]
	// elements.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3};
	// assert.Equal(t, FromVec(a).Count(), 3);
	//
	// var a = []int{1, 2, 3, 4, 5};
	// assert.Equal(t, FromVec(a).Count(), 5);
	Count() uint
	// Partition consumes an iterator, creating two collections from it.
	//
	// The predicate passed to `partition()` can return `true`, or `false`.
	// `partition()` returns a pair, all the elements for which it returned
	// `true`, and all the elements for which it returned `false`.
	Partition(f func(T) bool) (truePart []T, falsePart []T)
	// IsPartitioned checks if the elements of this iterator are partitioned according to the given predicate,
	// such that all those that return `true` precede all those that return `false`.
	IsPartitioned(predicate func(T) bool) bool
	// Fold folds every element into an accumulator by applying an operation,
	// returning the final
	//
	// `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 data iteration.
	//
	// The initial value is the value the accumulator will have on the first
	// call.
	//
	// After applying this closure to every element of the data, `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 data,
	// might not terminate for infinite iterators, even on interfaces 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
	//
	// # Note to Implementors
	//
	// Several of the other (forward) methods have default implementations in
	// terms of this one, so try to implement this explicitly if it can
	// do something better than the default `for` loop implementation.
	//
	// In particular, try to have this call `Fold()` on the internal parts
	// from which this data is composed.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3};
	//
	// the sum of iAll the elements of the array
	// var sum = FromVec(a).Fold((0, func(acc any, x int) any { return acc.(int) + x });
	//
	// assert.Equal(t, sum, 6);
	//
	// Let's walk through each step of the iteration here:
	//
	// | element | acc | x | result |
	// |---------|-----|---|--------|
	// |         | 0   |   |        |
	// | 1       | 0   | 1 | 1      |
	// | 2       | 1   | 2 | 3      |
	// | 3       | 3   | 3 | 6      |
	//
	// And so, our final result, `6`.
	Fold(init any, fold func(any, T) any) any
	// TryFold a data method that applies a function as long as it returns
	// successfully, producing a single, final value.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3};
	//
	// the checked sum of iAll the elements of the array
	// var sum = FromVec(a).TryFold(0, func(acc any, x int) gust.AnyCtrlFlow { return gust.Continue[any,any](acc.(int)+x) });
	//
	// assert.Equal(t,  gust.Continue[any,any](6), sum)
	TryFold(init any, fold func(any, T) gust.AnyCtrlFlow) gust.AnyCtrlFlow
	// Last consumes the data, returning the iLast element.
	//
	// This method will evaluate the data until it returns [`gust.None[T]()`]. While
	// doing so, it keeps track of the current element. After [`gust.None[T]()`] is
	// returned, `Last()` will then return the iLast element it saw.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3};
	// assert.Equal(t, FromVec(a).Last(), gust.Some(3));
	//
	// var a = [1, 2, 3, 4, 5];
	// assert.Equal(t, FromVec(a).Last(), gust.Some(5));
	Last() gust.Option[T]
	// AdvanceBy advances the data by `n` elements.
	//
	// This method will eagerly skip `n` elements by calling [`Next`] up to `n`
	// times until [`gust.None[T]()`] is encountered.
	//
	// `AdvanceBy(n)` will return [`gust.NonErrable[uint]()`] if the data successfully advances by
	// `n` elements, or [`gust.ToErrable[uint](k)`] if [`gust.None[T]()`] is encountered, where `k` is the number
	// of elements the data is advanced by before running out of elements (i.e. the
	// length of the data). Note that `k` is always less than `n`.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3, 4};
	// var iter = FromVec(a);
	//
	// assert.Equal(t, iter.AdvanceBy(2), gust.NonErrable[uint]());
	// assert.Equal(t, iter.Next(), gust.Some(3));
	// assert.Equal(t, iter.AdvanceBy(0), gust.NonErrable[uint]());
	// assert.Equal(t, iter.AdvanceBy(100), gust.ToErrable[uint](1)); // only `4` was skipped
	AdvanceBy(n uint) gust.Errable[uint]
	// Nth returns the `n`th element of the data.
	//
	// Like most indexing operations, the iCount starts from zero, so `Nth(0)`
	// returns the first value, `Nth(1)` the second, and so on.
	//
	// Note that `All()` preceding elements, as well as the returned element, will be
	// consumed from the data. That means that the preceding elements will be
	// discarded, and also that calling `Nth(0)` multiple times on the same data
	// will return different elements.
	//
	// `Nth()` will return [`gust.None[T]()`] if `n` is greater than or equal to the length of the
	// data.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3};
	// assert.Equal(t, FromVec(a).Nth(1), gust.Some(2));
	//
	// Calling `Nth()` multiple times doesn't rewind the data:
	//
	// var a = []int{1, 2, 3};
	//
	// var iter = FromVec(a);
	//
	// assert.Equal(t, iter.Nth(1), gust.Some(2));
	// assert.Equal(t, iter.Nth(1), gust.None[int]());
	//
	// Returning `gust.None[T]()` if there are less than `n + 1` elements:
	//
	// var a = []int{1, 2, 3};
	// assert.Equal(t, FromVec(a).Nth(10), gust.None[int]());
	Nth(n uint) gust.Option[T]
	// ForEach calls a closure on each element of a data.
	//
	// This is equivalent to using a [`for`] loop on the data, although
	// `break` and `continue` are not possible from a closure. It's generally
	// more idiomatic to use a `for` loop, but `ForEach` may be more legible
	// when processing items at the end of longer data chains. In some
	// cases `ForEach` may also be faster than a loop, because it will use
	// internal iteration on adapters like `chainIterator`.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var c = make(chan int, 1000)
	// FromRange(0, 5).ToMap(func(x A)any{return x * 2 + 1})
	//
	//	.ForEach(func(x any){ c<-x });
	//
	// var v = FromChan(c).Collect();
	// assert.Equal(t, v, []int{1, 3, 5, 7, 9});
	ForEach(f func(T))
	// TryForEach is an iterator method that applies a fallible function to each item in the
	// iterator, stopping at the first error and returning that error.
	TryForEach(f func(T) gust.AnyCtrlFlow) gust.AnyCtrlFlow
	// Reduce reduces the elements to a single one, by repeatedly applying a reducing
	// operation.
	//
	// If the data is empty, returns [`gust.None[T]()`]; 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 data as the initial accumulator value, folding
	// every subsequent element into it.
	//
	// # Example
	//
	// Find the maximum value:
	//
	//	func findMax[A any](iter: Iterator[A])  Option[A] {
	//	    iter.Reduce(func(accum A, item A) A {
	//	        if accum >= item { accum } else { item }
	//	    })
	//	}
	//
	// var a = []int{10, 20, 5, -23, 0};
	// var b = []int{};
	//
	// assert.Equal(t, findMax(FromVec(a)), gust.Some(20));
	// assert.Equal(t, findMax(FromVec(b)), gust.None[int]());
	Reduce(f func(accum T, item T) T) gust.Option[T]
	// TryReduce reduces the elements to a single one by repeatedly applying a reducing operation.
	// If the closure returns a failure, the failure is propagated back to the caller immediately.
	//
	// When called on an empty iterator, this function will return `Ok(None)` depending on the type
	// of the provided closure.
	//
	// For iterators with at least one element, this is essentially the same as calling
	// [`TryFold()`] with the first element of the iterator as the initial accumulator value.
	TryReduce(f func(accum T, item T) gust.Result[T]) gust.Result[gust.Option[T]]
	// All tests if every element of the data matches a predicate.
	//
	// `All()` takes a closure that returns `true` or `false`. It applies
	// this closure to each element of the data, and if they iAll return
	// `true`, then so does `All()`. If any of them return `false`, it
	// returns `false`.
	//
	// `All()` is short-circuiting; in other words, it will stop processing
	// as soon as it finds a `false`, given that no matter what else happens,
	// the result will also be `false`.
	//
	// An empty data returns `true`.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3};
	//
	// assert.True(t, FromVec(a).All(func(x A) bool { return x > 0}));
	//
	// assert.True(t, !FromVec(a).All(func(x A) bool { return x > 2}));
	//
	// Stopping at the first `false`:
	//
	// var a = []int{1, 2, 3};
	//
	// var iter = FromVec(a);
	//
	// assert.True(t, !iter.All(func(x A) bool { return x != 2}));
	//
	// we can still use `iter`, as there are more elements.
	// assert.Equal(t, iter.Next(), gust.Some(3));
	All(predicate func(T) bool) bool
	// Any tests if any element of the data matches a predicate.
	//
	// `Any()` takes a closure that returns `true` or `false`. It applies
	// this closure to each element of the data, and if any of them return
	// `true`, then so does `Any()`. If they iAll return `false`, it
	// returns `false`.
	//
	// `Any()` is short-circuiting; in other words, it will stop processing
	// as soon as it finds a `true`, given that no matter what else happens,
	// the result will also be `true`.
	//
	// An empty data returns `false`.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3};
	//
	// assert.True(t, FromVec(a).Any(func(x A) bool{return x>0}));
	//
	// assert.True(t, !FromVec(a).Any(func(x A) bool{return x>5}));
	//
	// Stopping at the first `true`:
	//
	// var a = []int{1, 2, 3};
	//
	// var iter = FromVec(a);
	//
	// assert.True(t, iter.Any(func(x A) bool { return x != 2}));
	//
	// we can still use `iter`, as there are more elements.
	// assert.Equal(t, iter.Next(), gust.Some(2));
	Any(predicate func(T) bool) bool
	// Find searches for an element of a data that satisfies a predicate.
	//
	// `Find()` takes a closure that returns `true` or `false`. It applies
	// this closure to each element of the data, and if any of them return
	// `true`, then `Find()` returns [`gust.Some(element)`]. If they iAll return
	// `false`, it returns [`gust.None[T]()`].
	//
	// `Find()` is short-circuiting; in other words, it will stop processing
	// as soon as the closure returns `true`.
	//
	// Because `Find()` takes a reference, and many iterators iterate over
	// references, this leads to a possibly confusing situation where the
	// argument is a double reference. You can see this effect in the
	// examples below, with `&&x`.
	//
	// [`gust.Some(element)`]: gust.Some
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3};
	//
	// assert.Equal(t, FromVec(a).Find(func(x A) bool{return x==2}), gust.Some(2));
	//
	// assert.Equal(t, FromVec(a).Find(func(x A) bool{return x==5}), gust.None[int]());
	//
	// Stopping at the first `true`:
	//
	// var a = []int{1, 2, 3};
	//
	// var iter = FromVec(a);
	//
	// assert.Equal(t, iter.Find(func(x A) bool{return x==2}), gust.Some(2));
	//
	// we can still use `iter`, as there are more elements.
	// assert.Equal(t, iter.Next(), gust.Some(3));
	//
	// Note that `iter.Find(f)` is equivalent to `iter.ToFilter(f).Next()`.
	Find(predicate func(T) bool) gust.Option[T]
	// FindMap applies function to the elements of data and returns
	// the first non-none
	//
	// `FindMap(f)` is equivalent to `ToFilterMap(f).Next()`.
	//
	// # Examples
	//
	// var a = []string{"lol", "NaN", "2", "5"};
	//
	// var first_number = FromVec(a).FindMap(func(s A) Option[any]{ return gust.Ret[any](strconv.Atoi(s)).Ok()});
	//
	// assert.Equal(t, first_number, gust.Some(2));
	FindMap(f func(T) gust.Option[T]) gust.Option[T]
	// XFindMap applies function to the elements of data and returns
	// the first non-none
	XFindMap(f func(T) gust.Option[any]) gust.Option[any]
	// TryFind applies function to the elements of data and returns
	// the first true result or the first error.
	//
	// # Examples
	//
	// var a = []string{"1", "2", "lol", "NaN", "5"};
	//
	//	var is_my_num = func(s string, search int) Result[bool] {
	//	    return ret.Map(gust.Ret(strconv.Atoi(s)), func(x int) bool { return x == search })
	//	}
	//
	// var result = FromVec(a).TryFind(func(s string)bool{return is_my_num(s, 2)});
	// assert.Equal(t, result, A(Some("2")));
	//
	// var result = FromVec(a).TryFind(func(s string)bool{return is_my_num(s, 5)});
	// assert.True(t, result.IsErr());
	TryFind(predicate func(T) gust.Result[bool]) gust.Result[gust.Option[T]]
	// Position searches for an element in a data, returning its index.
	//
	// `Position()` takes a closure that returns `true` or `false`. It applies
	// this closure to each element of the data, and if one of them
	// returns `true`, then `Position()` returns [`gust.Some(index)`]. If iAll of
	// them return `false`, it returns [`gust.None[T]()`].
	//
	// `Position()` is short-circuiting; in other words, it will stop
	// processing as soon as it finds a `true`.
	//
	// # Overflow Behavior
	//
	// The method does no guarding against overflows, so if there are more
	// than [`math.MaxInt`] non-matching elements, it either produces the wrong
	// result or panics. If debug assertions are enabled, a panic is
	// guaranteed.
	//
	// # Panics
	//
	// This function might panic if the data has more than `math.MaxInt`
	// non-matching elements.
	//
	// [`gust.Some(index)`]: gust.Some
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{1, 2, 3};
	//
	// assert.Equal(t, FromVec(a).Position(func(x int)bool{return x==2}), gust.Some(1));
	//
	// assert.Equal(t, FromVec(a).Position(func(x int)bool{return x==5}), gust.None[int]());
	//
	// Stopping at the first `true`:
	//
	// var a = []int{1, 2, 3, 4};
	//
	// var iter = FromVec(a);
	//
	// assert.Equal(t, iter.Position(func(x int)bool{return x >= 2}), gust.Some(1));
	//
	// we can still use `iter`, as there are more elements.
	// assert.Equal(t, iter.Next(), gust.Some(3));
	//
	// The returned index depends on data state
	// assert.Equal(t, iter.Position(func(x int)bool{return x == 4}), gust.Some(0));
	Position(predicate func(T) bool) gust.Option[int]
	// ToStepBy creates a data starting at the same point, but stepping by
	// the given amount at each iteration.
	//
	// Note 1: The first element of the data will always be returned,
	// regardless of the step given.
	//
	// Note 2: The time at which ignored elements are pulled is not fixed.
	// `stepByIterator` behaves like the sequence `iter.Next()`, `iter.Nth(step-1)`,
	// `iter.Nth(step-1)`, …, but is also free to behave like the sequence.
	//
	// # Examples
	//
	// Basic usage:
	//
	// var a = []int{0, 1, 2, 3, 4, 5};
	// var iter = FromVec(a).ToStepBy(2);
	//
	// assert.Equal(t, iter.Next(), gust.Some(0));
	// assert.Equal(t, iter.Next(), gust.Some(2));
	// assert.Equal(t, iter.Next(), gust.Some(4));
	// assert.Equal(t, iter.Next(), gust.None[T]());
	ToStepBy(step uint) Iterator[T]
	// ToFilter 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.
	//
	// # Examples
	//
	// Basic usage:
	//
	// “`
	// var a = []int{0, 1, 2};
	//
	// var iter = FromVec(a).ToFilter(func(x int)bool{return x>0});
	//
	// assert.Equal(iter.Next(), gust.Some(&1));
	// assert.Equal(iter.Next(), gust.Some(&2));
	// assert.Equal(iter.Next(), gust.None[int]());
	// “`
	//
	// Note that `iter.ToFilter(f).Next()` is equivalent to `iter.Find(f)`.
	ToFilter(f func(T) bool) Iterator[T]
	// ToFilterMap creates an iterator that both filters and maps.
	//
	// The returned iterator yields only the `value`s for which the supplied
	// closure returns `gust.Some(value)`.
	//
	// `ToFilterMap` can be used to make chains of [`ToFilter`] and [`ToMap`] more
	// concise. The example below shows how a `ToMap().ToFilter().ToMap()` can be
	// shortened to a single call to `ToFilterMap`.
	//
	// # Examples
	//
	// Basic usage:
	//
	// “`
	// var a = []string{"1", "two", "NaN", "four", "5"}
	//
	// var iter = FromVec(a).ToFilterMap(|s| s.parse().ok());
	//
	// assert.Equal(iter.Next(), gust.Some(1));
	// assert.Equal(iter.Next(), gust.Some(5));
	// assert.Equal(iter.Next(), gust.None[string]());
	// “`
	ToFilterMap(f func(T) gust.Option[T]) Iterator[T]
	// ToXFilterMap creates an iterator that both filters and maps.
	ToXFilterMap(f func(T) gust.Option[any]) Iterator[any]
	// ToChain takes two iterators and creates a new data over both in sequence.
	//
	// `ToChain()` will return a new data which will first iterate over
	// values from the first data and then over values from the second
	// data.
	//
	// In other words, it links two iterators together, in a chain. 🔗
	//
	// # Examples
	//
	// Basic usage:
	//
	//
	// var a1 = []int{1, 2, 3};
	// var a2 = []int{4, 5, 6};
	//
	// var iter = FromVec(a1).ToChain(FromVec(a2));
	//
	// assert.Equal(t, iter.Next(), gust.Some(1));
	// assert.Equal(t, iter.Next(), gust.Some(2));
	// assert.Equal(t, iter.Next(), gust.Some(3));
	// assert.Equal(t, iter.Next(), gust.Some(4));
	// assert.Equal(t, iter.Next(), gust.Some(5));
	// assert.Equal(t, iter.Next(), gust.Some(6));
	// assert.Equal(t, iter.Next(), gust.None[int]());
	//
	ToChain(other Iterator[T]) Iterator[T]
	// ToMap takes a closure and creates an iterator which calls that closure on each
	// element.
	//
	// If you are good at thinking in types, you can think of `ToMap()` like this:
	// If you have an iterator that gives you elements of some type `A`, and
	// you want an iterator of some other type `B`, you can use `ToMap()`,
	// passing a closure that takes an `A` and returns a `B`.
	//
	// `ToMap()` is conceptually similar to a [`for`] loop. However, as `ToMap()` is
	// lazy, it is best used when you're already working with other iterators.
	// If you're doing some sort of looping for a side effect, it's considered
	// more idiomatic to use [`for`] than `ToMap()`.
	//
	// # Examples
	//
	// Basic usage:
	//
	// “`
	// var a = []int{1, 2, 3};
	//
	// var iter = FromVec(a).ToMap(func(x)int{ return 2 * x});
	//
	// assert.Equal(iter.Next(), gust.Some(2));
	// assert.Equal(iter.Next(), gust.Some(4));
	// assert.Equal(iter.Next(), gust.Some(6));
	// assert.Equal(iter.Next(), gust.None[int]());
	// “`
	//
	ToMap(f func(T) T) Iterator[T]
	// ToXMap takes a closure and creates an iterator which calls that closure on each
	// element.
	ToXMap(f func(T) any) Iterator[any]
	// ToInspect takes a closure and executes it with each element.
	ToInspect(f func(T)) Iterator[T]
	// ToFuse creates an iterator which ends after the first [`gust.None[T]()`].
	//
	// After an iterator returns [`gust.None[T]()`], future calls may or may not yield
	// [`gust.Some(T)`] again. `ToFuse()` adapts an iterator, ensuring that after a
	// [`gust.None[T]()`] is given, it will always return [`gust.None[T]()`] forever.
	ToFuse() Iterator[T]
	// ToPeekable creates an iterator which can use the [`Peek`] methods
	// to look at the next element of the iterator without consuming it.
	ToPeekable() PeekableIterator[T]
	// ToIntersperse creates a new iterator which places a copy of `separator` between adjacent
	// items of the original iterator.
	ToIntersperse(separator T) Iterator[T]
	// ToIntersperseWith creates a new iterator which places an item generated by `separator`
	// between adjacent items of the original iterator.
	ToIntersperseWith(separator func() T) Iterator[T]
	// ToSkipWhile creates an iterator that [`skip`]s elements based on a predicate.
	//
	// `ToSkipWhile()` 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, `ToSkipWhile()`'s job is over, and the
	// rest of the elements are yielded.
	ToSkipWhile(predicate func(T) bool) Iterator[T]
	// ToTakeWhile creates an iterator that yields elements based on a predicate.
	//
	// `ToTakeWhile()` 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, `ToTakeWhile()`'s job is over, and the
	// rest of the elements are ignored.
	ToTakeWhile(predicate func(T) bool) Iterator[T]
	// ToMapWhile creates an iterator that both yields elements based on a predicate and maps.
	//
	// `ToMapWhile()` takes a closure as an argument. It will call this
	// closure on each element of the iterator, and yield elements
	// while it returns [`Some`].
	ToMapWhile(predicate func(T) gust.Option[T]) Iterator[T]
	// ToXMapWhile creates an iterator that both yields elements based on a predicate and maps.
	//
	// `ToMapWhile()` takes a closure as an argument. It will call this
	// closure on each element of the iterator, and yield elements
	// while it returns [`Some`].
	ToXMapWhile(predicate func(T) gust.Option[any]) Iterator[any]
	// ToSkip creates an iterator that skips the first `n` elements.
	//
	// `ToSkip(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.
	//
	// Rather than overriding this method directly, instead override the `Nth` method.
	ToSkip(n uint) Iterator[T]
	// ToTake creates an iterator that yields the first `n` elements, or fewer
	// if the underlying iterator ends sooner.
	//
	// `ToTake(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 the
	// (fewer than `n`) elements of the original iterator.
	ToTake(n uint) Iterator[T]
	// ToScan is an iterator adapter similar to [`Fold`] that holds internal state and
	// produces a new iterator.
	//
	// [`Fold`]: Iterator.Fold
	//
	// `ToScan()` 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 assign to 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
	// yielded by the iterator.
	ToScan(initialState any, f func(state *any, item T) gust.Option[any]) Iterator[any]
}

Iterator is an interface for dealing with iterators.

Example
package main

import (
	"fmt"

	"github.com/andeya/gust/iter"
)

func main() {
	var v = []int{1, 2, 3, 4, 5}
	iter.FromVec(v).ForEach(func(x int) {
		fmt.Printf("%d\n", x)
	})
}
Output:

1
2
3
4
5

func EnumChan

func EnumChan[T any](c chan T) Iterator[gust.VecEntry[T]]

EnumChan creates an iterator with index from a channel.

func EnumIterable

func EnumIterable[T any](data gust.Iterable[T]) Iterator[gust.VecEntry[T]]

EnumIterable creates an iterator with index from an Iterable.

func FromChan

func FromChan[T any](c chan T) Iterator[T]

FromChan creates an iterator from a channel.

func FromIterable

func FromIterable[T any](data gust.Iterable[T]) Iterator[T]

FromIterable creates an iterator from an Iterable.

func ToEnumerate added in v1.0.0

func ToEnumerate[T any](iter Iterator[T]) Iterator[gust.VecEntry[T]]

ToEnumerate creates an iterator that yields pairs of the index and the value.

func ToFilterMap added in v1.0.0

func ToFilterMap[T any, B any](iter Iterator[T], f func(T) gust.Option[B]) Iterator[B]

ToFilterMap creates an iterator that both filters and maps.

The returned iterator yields only the `value`s for which the supplied closure returns `gust.Some(value)`.

func ToFlatMap added in v1.0.0

func ToFlatMap[T any, B any](iter Iterator[T], f func(T) Iterator[B]) Iterator[B]

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

The [`ToMap`] 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. `ToFlatMap()` will remove this extra layer on its own.

You can think of `ToFlatMap(f)` as the semantic equivalent of [`ToMap`]ping, and then [`ToFlatten`]ing as in `ToMap(f).ToFlatten()`.

Another way of thinking about `ToFlatMap()`: [`ToMap`]'s closure returns one item for each element, and `ToFlatMap()`'s closure returns an iterator for each element.

func ToFlatten added in v1.0.0

func ToFlatten[I gust.Iterable[T], T any](iter Iterator[I]) Iterator[T]

ToFlatten creates an iterator that flattens nested structure.

func ToMap added in v1.0.0

func ToMap[T any, B any](iter Iterator[T], f func(T) B) Iterator[B]

ToMap takes a closure and creates an iterator which calls that closure on each element.

If you are good at thinking in types, you can think of `ToMap()` like this: If you have an iterator that gives you elements of some type `A`, and you want an iterator of some other type `B`, you can use `ToMap()`, passing a closure that takes an `A` and returns a `B`.

`ToMap()` is conceptually similar to a [`for`] loop. However, as `ToMap()` is lazy, it is best used when you're already working with other iterators. If you're doing some sort of looping for a side effect, it's considered more idiomatic to use [`for`] than `ToMap()`.

Examples

Basic usage:

``` var a = []int{1, 2, 3};

var iter = FromVec(a).ToMap(func(x)int{ return 2 * x});

assert.Equal(iter.Next(), gust.Some(2)); assert.Equal(iter.Next(), gust.Some(4)); assert.Equal(iter.Next(), gust.Some(6)); assert.Equal(iter.Next(), gust.None[int]()); ```

func ToMapWhile added in v1.0.0

func ToMapWhile[T any, B any](iter Iterator[T], predicate func(T) gust.Option[B]) Iterator[B]

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

`ToMapWhile()` takes a closure as an argument. It will call this closure on each element of the iterator, and yield elements while it returns [`Some`].

func ToScan added in v1.0.0

func ToScan[T any, St any, B any](iter Iterator[T], initialState St, f func(state *St, item T) gust.Option[B]) Iterator[B]

ToScan is an iterator adapter similar to [`Fold`] that holds internal state and produces a new iterator.

[`Fold`]: Iterator.Fold

`ToScan()` 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 assign to 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 yielded by the iterator.

func ToUnique added in v1.2.2

func ToUnique[T comparable](iter Iterator[T]) Iterator[T]

ToUnique return an iterator adaptor that filters out elements that have already been produced once during the iteration. Duplicates are detected using hash and equality.

Clones of visited elements are stored in a hash set in the iterator.

The iterator is stable, returning the non-duplicate items in the order in which they occur in the adapted iterator. In a set of duplicate items, the first item encountered is the item retained.

``` var data = FromElements(10, 20, 30, 20, 40, 10, 50); ToUnique(data).Collect() // [10, 20, 30, 40, 50] ```

func ToUniqueBy added in v1.2.2

func ToUniqueBy[T any, K comparable](iter Iterator[T], f func(T) K) Iterator[T]

ToUniqueBy return an iterator adaptor that filters out elements that have already been produced once during the iteration.

Duplicates are detected by comparing the key they map to with the keying function `f` by hash and equality. The keys are stored in a hash set in the iterator.

The iterator is stable, returning the non-duplicate items in the order in which they occur in the adapted iterator. In a set of duplicate items, the first item encountered is the item retained.

``` var data = FromElements("a", "bb", "aa", "c", "ccc"); ToUniqueBy(data, func(s string)int {return len(s)}).Collect() // "a", "bb", "ccc" ```

func ToZip added in v1.0.0

func ToZip[A any, B any](a Iterator[A], b Iterator[B]) Iterator[gust.Pair[A, B]]

ToZip 'Zips up' two iterators into a single iterator of pairs.

`ToZip()` 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 [`gust.None[A]()`], [`Next`] from the zipped iterator will return [gust.None[A]()]. If the zipped iterator has no more elements to return then each further attempt to advance it will first try to advance the first iterator at most one time and if it still yielded an item try to advance the second iterator at most one time.

type PeekableIterator

type PeekableIterator[T any] interface {
	Iterator[T]
	// contains filtered or unexported methods
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL