iterator

package
v1.20.7 Latest Latest
Warning

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

Go to latest
Published: Dec 31, 2025 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package iterator provides a complete implementation of Rust's Iterator trait in Go.

This package translates the Rust Iterator trait and its methods to Go, maintaining semantic equivalence while adapting to Go's type system and idioms. It provides 60+ methods for iterator manipulation, transformation, filtering, and consumption.

Examples

// Basic iteration
iter := iterator.FromSlice([]int{1, 2, 3})
for opt := iter.Next(); opt.IsSome(); opt = iter.Next() {
	fmt.Println(opt.Unwrap())
}

// Method chaining
result := iterator.FromSlice([]int{1, 2, 3, 4, 5}).
	Filter(func(x int) bool { return x%2 == 0 }).
	Map(func(x int) int { return x * x }).
	Collect() // []int{4, 16}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Cmp

Cmp lexicographically compares the elements of this Iterator with those of another.

Examples

assert.Equal(t, constraints.Less(), Cmp(FromSlice([]int{1}), FromSlice([]int{1})))
assert.Equal(t, constraints.Less(), Cmp(FromSlice([]int{1}), FromSlice([]int{1, 2})))
assert.Equal(t, constraints.Greater(), Cmp(FromSlice([]int{1, 2}), FromSlice([]int{1})))

func CmpBy

func CmpBy[T any, U any](a Iterator[T], b Iterator[U], cmp func(T, U) int) constraints.Ordering

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

Examples

var xs = []int{1, 2, 3, 4}
var ys = []int{1, 4, 9, 16}
var result = CmpBy(FromSlice(xs), FromSlice(ys), func(x, y int) int {
	if x*x < y {
		return -1
	}
	if x*x > y {
		return 1
	}
	return 0
})
assert.Equal(t, constraints.Equal(), result)

func DefaultSizeHint

func DefaultSizeHint[T any]() (uint, option.Option[uint])

DefaultSizeHint provides a default implementation of SizeHint that returns (0, None). This can be used by iterator implementations that don't have size information.

func Eq

func Eq[T comparable](a Iterator[T], b Iterator[T]) bool

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

Examples

assert.True(t, Eq(FromSlice([]int{1}), FromSlice([]int{1})))
assert.False(t, Eq(FromSlice([]int{1}), FromSlice([]int{1, 2})))

func EqBy

func EqBy[T any, U any](a Iterator[T], b Iterator[U], eq func(T, U) bool) bool

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

Examples

var xs = []int{1, 2, 3, 4}
var ys = []int{1, 4, 9, 16}
assert.True(t, EqBy(FromSlice(xs), FromSlice(ys), func(x, y int) bool { return x*x == y }))

func FindMap

func FindMap[T any, U any](iter Iterator[T], f func(T) option.Option[U]) option.Option[U]

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

FindMap(f) is equivalent to FilterMap(iter, f).Next().

Examples

var a = []string{"lol", "NaN", "2", "5"}
var firstNumber = FindMap(FromSlice(a), func(s string) option.Option[int] {
	if v, err := strconv.Atoi(s); err == nil {
		return option.Some(v)
	}
	return option.None[int]()
})
assert.Equal(t, option.Some(2), firstNumber)

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 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.

Examples

Basic usage:

var a = []int{1, 2, 3}
// the sum of all of the elements of the array
var sum = Fold(FromSlice(a), 0, func(acc int, x int) int { return acc + x })
assert.Equal(t, 6, sum)

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 Ge

func Ge[T constraints.Digit](a Iterator[T], b Iterator[T]) bool

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

Examples

assert.True(t, Ge(FromSlice([]int{1}), FromSlice([]int{1})))
assert.False(t, Ge(FromSlice([]int{1}), FromSlice([]int{1, 2})))
assert.True(t, Ge(FromSlice([]int{1, 2}), FromSlice([]int{1})))

func Gt

func Gt[T constraints.Digit](a Iterator[T], b Iterator[T]) bool

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

Examples

assert.False(t, Gt(FromSlice([]int{1}), FromSlice([]int{1})))
assert.False(t, Gt(FromSlice([]int{1}), FromSlice([]int{1, 2})))
assert.True(t, Gt(FromSlice([]int{1, 2}), FromSlice([]int{1})))

func IsSorted

func IsSorted[T constraints.Digit](iter Iterator[T]) bool

IsSorted checks if the elements of this iterator are sorted.

That is, for each element a and its following element b, a <= b must hold. If the iterator yields exactly zero or one element, true is returned.

Note that if T is only PartialOrd, but not Ord, the above definition implies that this function returns false if any two consecutive items are not comparable.

Examples

assert.True(t, IsSorted(FromSlice([]int{1, 2, 2, 9})))
assert.False(t, IsSorted(FromSlice([]int{1, 3, 2, 4})))
assert.True(t, IsSorted(FromSlice([]int{0})))
assert.True(t, IsSorted(Empty[int]()))

func IsSortedBy

func IsSortedBy[T any](iter Iterator[T], compare func(T, T) bool) bool

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

Instead of using PartialOrd::partial_cmp, this function uses the given compare function to determine whether two elements are to be considered in sorted order.

Examples

assert.True(t, IsSortedBy(FromSlice([]int{1, 2, 2, 9}), func(a, b int) bool { return a <= b }))
assert.False(t, IsSortedBy(FromSlice([]int{1, 2, 2, 9}), func(a, b int) bool { return a < b }))

func IsSortedByKey

func IsSortedByKey[T any, K constraints.Digit](iter Iterator[T], f func(T) K) bool

IsSortedByKey checks if the elements of this iterator are sorted using the given key extraction function.

Instead of comparing the iterator's elements directly, this function compares the keys of the elements, as determined by f. Apart from that, it's equivalent to IsSorted; see its documentation for more information.

Examples

assert.True(t, IsSortedByKey(FromSlice([]string{"c", "bb", "aaa"}), func(s string) int { return len(s) }))
assert.False(t, IsSortedByKey(FromSlice([]int{-2, -1, 0, 3}), func(n int) int {
	if n < 0 {
		return -n
	}
	return n
}))

func Le

func Le[T constraints.Digit](a Iterator[T], b Iterator[T]) bool

Le determines if the elements of this Iterator are lexicographically less or equal to those of another.

Examples

assert.True(t, Le(FromSlice([]int{1}), FromSlice([]int{1})))
assert.True(t, Le(FromSlice([]int{1}), FromSlice([]int{1, 2})))
assert.False(t, Le(FromSlice([]int{1, 2}), FromSlice([]int{1})))

func Lt

func Lt[T constraints.Digit](a Iterator[T], b Iterator[T]) bool

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

Examples

assert.False(t, Lt(FromSlice([]int{1}), FromSlice([]int{1})))
assert.True(t, Lt(FromSlice([]int{1}), FromSlice([]int{1, 2})))
assert.False(t, Lt(FromSlice([]int{1, 2}), FromSlice([]int{1})))

func Max

func Max[T constraints.Ord](iter Iterator[T]) option.Option[T]

Max returns the maximum element of an iterator.

If several elements are equally maximum, the last element is returned. If the iterator is empty, option.None[T]() is returned.

Note that f32/f64 doesn't implement Ord due to NaN being incomparable. You can work around this by using Reduce:

var max = Reduce(FromSlice([]float32{2.4, float32(math.NaN()), 1.3}), func(a, b float32) float32 {
	if a > b {
		return a
	}
	return b
})

Examples

var a = []int{1, 2, 3}
var b = []int{}
assert.Equal(t, option.Some(3), Max(FromSlice(a)))
assert.Equal(t, option.None[int](), Max(FromSlice(b)))

func MaxByKey

func MaxByKey[T any, K constraints.Ord](iter Iterator[T], f func(T) K) option.Option[T]

MaxByKey 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, option.None[T]() is returned.

Examples

var a = []int{-3, 0, 1, 5, -10}
var max = MaxByKey(FromSlice(a), func(x int) int {
	if x < 0 {
		return -x
	}
	return x
})
assert.Equal(t, option.Some(-10), max)

func Min

func Min[T constraints.Ord](iter Iterator[T]) option.Option[T]

Min returns the minimum element of an iterator.

If several elements are equally minimum, the first element is returned. If the iterator is empty, option.None[T]() is returned.

Note that f32/f64 doesn't implement Ord due to NaN being incomparable. You can work around this by using Reduce:

var min = Reduce(FromSlice([]float32{2.4, float32(math.NaN()), 1.3}), func(a, b float32) float32 {
	if a < b {
		return a
	}
	return b
})

Examples

var a = []int{1, 2, 3}
var b = []int{}
assert.Equal(t, option.Some(1), Min(FromSlice(a)))
assert.Equal(t, option.None[int](), Min(FromSlice(b)))

func MinByKey

func MinByKey[T any, K constraints.Ord](iter Iterator[T], f func(T) K) option.Option[T]

MinByKey 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, option.None[T]() is returned.

Examples

var a = []int{-3, 0, 1, 5, -10}
var min = MinByKey(FromSlice(a), func(x int) int {
	if x < 0 {
		return -x
	}
	return x
})
assert.Equal(t, option.Some(0), min)

func Ne

func Ne[T comparable](a Iterator[T], b Iterator[T]) bool

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

Examples

assert.False(t, Ne(FromSlice([]int{1}), FromSlice([]int{1})))
assert.True(t, Ne(FromSlice([]int{1}), FromSlice([]int{1, 2})))

func PartialCmp

PartialCmp lexicographically compares the PartialOrd 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.

Examples

var result = PartialCmp(FromSlice([]float64{1.0}), FromSlice([]float64{1.0}))
assert.Equal(t, option.Some(constraints.Equal()), result)

var result2 = PartialCmp(FromSlice([]float64{1.0}), FromSlice([]float64{1.0, 2.0}))
assert.Equal(t, option.Some(constraints.Less()), result2)

// For floating-point numbers, NaN does not have a total order
var nan = []float64{0.0 / 0.0}
var result3 = PartialCmp(FromSlice(nan), FromSlice([]float64{1.0}))
assert.Equal(t, option.None[constraints.Ordering](), result3)

func PartialCmpBy

func PartialCmpBy[T any, U any](a Iterator[T], b Iterator[U], partialCmp func(T, U) option.Option[constraints.Ordering]) option.Option[constraints.Ordering]

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

Examples

var xs = []float64{1.0, 2.0, 3.0, 4.0}
var ys = []float64{1.0, 4.0, 9.0, 16.0}
var result = PartialCmpBy(FromSlice(xs), FromSlice(ys), func(x, y float64) option.Option[constraints.Ordering] {
	if x*x < y {
		return option.Some(constraints.Less())
	}
	if x*x > y {
		return option.Some(constraints.Greater())
	}
	return option.Some(constraints.Equal())
})
assert.Equal(t, option.Some(constraints.Equal()), result)

func Product

func Product[T constraints.Digit](iter Iterator[T]) T

Product iterates over the entire iterator, multiplying all the elements

An empty iterator returns the one value of the type.

Panics

When calling Product() and a primitive integer type is being returned, method will panic if the computation overflows and overflow checks are enabled.

Examples

var factorial = func(n int) int {
	return Product(FromRange(1, n+1))
}
assert.Equal(t, 1, factorial(0))
assert.Equal(t, 1, factorial(1))
assert.Equal(t, 120, factorial(5))

func Pull2

func Pull2[K any, V any](it Iterator[pair.Pair[K, V]]) (next func() (K, V, bool), stop func())

Pull2 converts the Iterator[pair.Pair[K, V]] to a pull-style iterator using Go's standard iterator.Pull2. This returns two functions: next (to pull key-value pairs) and stop (to stop iteration). The caller should defer stop() to ensure proper cleanup.

Examples

iter1 := FromSlice([]int{1, 2, 3})
iter2 := FromSlice([]string{"a", "b", "c"})
zipped := Zip(iter1, iter2)
next, stop := Pull2(zipped)
defer stop()

// Pull key-value pairs manually
for {
	k, v, ok := next()
	if !ok {
		break
	}
	fmt.Println(k, v)
}

func Rfind

func Rfind[T any](de DoubleEndedIterator[T], predicate func(T) bool) option.Option[T]

Rfind searches for an element of an iterator from the back that satisfies a predicate (function version).

Examples

var a = []int{1, 2, 3}
var deIter = FromSlice(a).MustToDoubleEnded()
assert.Equal(t, option.Some(2), Rfind(deIter, func(x int) bool { return x == 2 }))

func Rfold

func Rfold[T any, B any](de DoubleEndedIterator[T], init B, f func(B, T) B) B

Rfold folds every element into an accumulator by applying an operation, starting from the back (generic version).

Examples

var a = []int{1, 2, 3}
var deIter = FromSlice(a).MustToDoubleEnded()
var sum = Rfold(deIter, 0, func(acc int, x int) int { return acc + x })
assert.Equal(t, 6, sum)

func Seq2

func Seq2[K any, V any](it Iterator[pair.Pair[K, V]]) iter.Seq2[K, V]

Seq2 converts the Iterator[pair.Pair[K, V]] to Go's standard iterator.Seq2[K, V]. This allows using gust pair iterators with Go's built-in key-value iteration support.

Examples

// Convert Zip iterator to Go Seq2
iter1 := FromSlice([]int{1, 2, 3})
iter2 := FromSlice([]string{"a", "b", "c"})
zipped := Zip(iter1, iter2)
for k, v := range Seq2(zipped) {
	fmt.Println(k, v) // prints 1 a, 2 b, 3 c
}

// Works with Go's standard library functions
enumerated := Enumerate(FromSlice([]string{"a", "b", "c"}))
for idx, val := range Seq2(enumerated) {
	fmt.Println(idx, val) // prints 0 a, 1 b, 2 c
}

func Sum

func Sum[T constraints.Digit](iter Iterator[T]) T

Sum sums the elements of an iterator.

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

An empty iterator returns the *additive identity* ("zero") of the type, which is 0 for integers and -0.0 for floats.

Panics

When calling Sum() and a primitive integer type is being returned, this method will panic if the computation overflows and overflow checks are enabled.

Examples

var a = []int{1, 2, 3}
var sum = Sum(FromSlice(a))
assert.Equal(t, 6, sum)

var b = []float64{}
var sumFloat = Sum(FromSlice(b))
assert.Equal(t, -0.0, sumFloat)

func TryFold

func TryFold[T any, B any](iter Iterator[T], init B, f func(B, T) result.Result[B]) result.Result[B]

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

TryFold() takes two arguments: an initial value, and a closure with two arguments: an 'accumulator', and an element. The closure either returns successfully, with the value that the accumulator should have for the next iteration, or it returns failure, with an error value that is propagated back to the caller immediately (short-circuiting).

The initial value is the value the accumulator will have on the first call. If applying the closure succeeded against every element of the iterator, TryFold() returns the final accumulator as success.

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

Examples

Basic usage:

var a = []int{1, 2, 3}
// the checked sum of all of the elements of the array
var sum = TryFold(FromSlice(a), 0, func(acc int, x int) result.Result[int] {
	// Simulate checked addition
	if acc > 100 {
		return result.TryErr[int](errors.New("overflow"))
	}
	return result.Ok(acc + x)
})
assert.True(t, sum.IsOk())
assert.Equal(t, 6, sum.Unwrap())

Short-circuiting:

var a = []int{10, 20, 30, 100, 40, 50}
var iter = FromSlice(a)
// This sum overflows when adding the 100 element
var sum = TryFold(iter, 0, func(acc int, x int) result.Result[int] {
	if acc+x > 50 {
		return result.TryErr[int](errors.New("overflow"))
	}
	return result.Ok(acc + x)
})
assert.True(t, sum.IsErr())

func TryForEach

func TryForEach[T any, B any](iter Iterator[T], f func(T) result.Result[B]) result.Result[B]

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.

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

Examples

var data = []string{"no_tea.txt", "stale_bread.json", "torrential_rain.png"}
var res = TryForEach(FromSlice(data), func(x string) result.Result[any] {
	fmt.Println(x)
	return result.Ok[any](nil)
})
assert.True(t, res.IsOk())

func TryRfold

func TryRfold[T any, B any](de DoubleEndedIterator[T], init B, f func(B, T) result.Result[B]) result.Result[B]

TryRfold is the reverse version of TryFold: it takes elements starting from the back of the iterator (generic version).

Examples

var a = []string{"1", "2", "3"}
var deIter = FromSlice(a).MustToDoubleEnded()
var sum = TryRfold(deIter, 0, func(acc int, s string) result.Result[int] {
	if v, err := strconv.Atoi(s); err == nil {
		return result.Ok(acc + v)
	}
	return result.TryErr[int](err)
})
assert.True(t, sum.IsOk())
assert.Equal(t, 6, sum.Unwrap())

func Unzip

func Unzip[T any, U any](iter Iterator[pair.Pair[T, U]]) ([]T, []U)

Unzip converts an iterator of pairs into a pair of containers.

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.

Examples

var a = []pair.Pair[int, string]{
	{A: 1, B: "a"},
	{A: 2, B: "b"},
	{A: 3, B: "c"},
}
var (left, right) = Unzip(FromSlice(a))
assert.Equal(t, []int{1, 2, 3}, left)
assert.Equal(t, []string{"a", "b", "c"}, right)

Types

type BitSetLike

type BitSetLike interface {
	// Size returns the number of bits in the bit set.
	Size() int
	// Get returns the value of the bit at the specified offset.
	//
	// Returns:
	//   - true if the bit at offset is set to 1
	//   - false if the bit at offset is set to 0
	//   - false if offset is out of range (offset < 0 or offset >= Size())
	Get(offset int) bool
}

BitSetLike is an interface for bit set implementations. This allows FromBitSet to work with any bit set implementation without depending on a specific package.

type ChunkResult

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

ChunkResult represents a success (T) or failure (T) for NextChunk. This is used when the error type is the same as the success type (e.g., []T).

func (ChunkResult[T]) IsErr

func (r ChunkResult[T]) IsErr() bool

IsErr returns true if the result is an error.

func (ChunkResult[T]) IsOk

func (r ChunkResult[T]) IsOk() bool

IsOk returns true if the result is ok.

func (ChunkResult[T]) Unwrap

func (r ChunkResult[T]) Unwrap() T

Unwrap returns the contained T value.

func (ChunkResult[T]) UnwrapErr

func (r ChunkResult[T]) UnwrapErr() T

UnwrapErr returns the contained error T value.

type DoubleEndedIterable

type DoubleEndedIterable[T any] interface {
	Iterable[T]
	SizeIterable[T]
	// NextBack returns the next value from the back of the sequence.
	// Returns Some(value) if there is a next value, None otherwise.
	NextBack() option.Option[T]
}

DoubleEndedIterable represents an iterable that can be iterated from both ends.

type DoubleEndedIterator

type DoubleEndedIterator[T any] struct {
	Iterator[T] // Embed Iterator to inherit all its methods
	// contains filtered or unexported fields
}

DoubleEndedIterator is the main double-ended iterator type that provides method chaining. It embeds Iterator[T] to inherit all Iterator methods, and adds double-ended specific methods. This enables Rust-like method chaining: deIter.Filter(...).NextBack().Rfold(...)

DoubleEndedIterator implements gust.Iterable[T] and gust.IterableSizeHint, so it can be used anywhere these interfaces are expected. It also inherits all Iterator[T] methods.

Examples

Basic usage:

var numbers = []int{1, 2, 3, 4, 5, 6}
var deIter = FromSlice(numbers).MustToDoubleEnded()

import "github.com/andeya/gust/option"
assert.Equal(t, option.Some(1), deIter.Next())
assert.Equal(t, option.Some(6), deIter.NextBack())
assert.Equal(t, option.Some(5), deIter.NextBack())
assert.Equal(t, option.Some(2), deIter.Next())
assert.Equal(t, option.Some(3), deIter.Next())
assert.Equal(t, option.Some(4), deIter.Next())
assert.Equal(t, option.None[int](), deIter.Next())
assert.Equal(t, option.None[int](), deIter.NextBack())

// Can use all Iterator methods:
var filtered = deIter.Filter(func(x int) bool { return x > 2 })
var collected = filtered.Collect()

func (DoubleEndedIterator[T]) AdvanceBackBy

func (de DoubleEndedIterator[T]) AdvanceBackBy(n uint) result.VoidResult

AdvanceBackBy advances the iterator from the back by n elements.

AdvanceBackBy is the reverse version of AdvanceBy. This method will eagerly skip n elements starting from the back by calling NextBack up to n times until None is encountered.

AdvanceBackBy(n) will return Ok[Void](nil) if the iterator successfully advances by n elements, or Err[Void](k) with value k if None is encountered, where k is remaining number of steps that could not be advanced because the iterator ran out. If iter is empty and n is non-zero, then this returns Err[Void](n). Otherwise, k is always less than n.

Calling AdvanceBackBy(0) can do meaningful work.

Examples

var a = []int{3, 4, 5, 6}
var deIter = FromSlice(a).MustToDoubleEnded()
assert.True(t, deIter.AdvanceBackBy(2).IsOk())
assert.Equal(t, option.Some(4), deIter.NextBack())
assert.True(t, deIter.AdvanceBackBy(0).IsOk())
assert.True(t, deIter.AdvanceBackBy(100).IsErr())

func (DoubleEndedIterator[T]) NextBack

func (de DoubleEndedIterator[T]) NextBack() option.Option[T]

NextBack removes and returns an element from the end of the iterator.

Returns None when there are no more elements.

Examples

var numbers = []int{1, 2, 3, 4, 5, 6}
var deIter = FromSlice(numbers).MustToDoubleEnded()
assert.Equal(t, option.Some(6), deIter.NextBack())
assert.Equal(t, option.Some(5), deIter.NextBack())
assert.Equal(t, option.Some(4), deIter.NextBack())
assert.Equal(t, option.Some(3), deIter.NextBack())
assert.Equal(t, option.Some(2), deIter.NextBack())
assert.Equal(t, option.Some(1), deIter.NextBack())
assert.Equal(t, option.None[int](), deIter.NextBack())

func (DoubleEndedIterator[T]) NthBack

func (de DoubleEndedIterator[T]) NthBack(n uint) option.Option[T]

NthBack returns the nth element from the end of the iterator.

This is essentially the reversed version of Nth(). Although like most indexing operations, the count starts from zero, so NthBack(0) returns the first value from the end, NthBack(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 NthBack(0) multiple times on the same iterator will return different elements.

NthBack() will return None if n is greater than or equal to the length of the iterator.

Examples

var a = []int{1, 2, 3}
var deIter = FromSlice(a).MustToDoubleEnded()
assert.Equal(t, option.Some(1), deIter.NthBack(2))
assert.Equal(t, option.Some(2), deIter.NthBack(1))
assert.Equal(t, option.Some(3), deIter.NthBack(0))
assert.Equal(t, option.None[int](), deIter.NthBack(10))

func (DoubleEndedIterator[T]) Remaining

func (de DoubleEndedIterator[T]) Remaining() uint

Remaining returns the number of elements remaining in the iterator.

Examples

var numbers = []int{1, 2, 3, 4, 5, 6} var deIter = FromSlice(numbers).MustToDoubleEnded() assert.Equal(t, uint(6), deIter.Remaining()) deIter.Next() assert.Equal(t, uint(5), deIter.Remaining()) deIter.NextBack() assert.Equal(t, uint(4), deIter.Remaining()) deIter.NextBack() assert.Equal(t, uint(3), deIter.Remaining()) deIter.NextBack() assert.Equal(t, uint(2), deIter.Remaining()) deIter.NextBack() assert.Equal(t, uint(1), deIter.Remaining()) deIter.NextBack() assert.Equal(t, uint(0), deIter.Remaining()) deIter.NextBack() assert.Equal(t, uint(0), deIter.Remaining())

func (DoubleEndedIterator[T]) Rfind

func (de DoubleEndedIterator[T]) Rfind(predicate func(T) bool) option.Option[T]

Rfind 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.

Examples

var a = []int{1, 2, 3}
var deIter = FromSlice(a).MustToDoubleEnded()
assert.Equal(t, option.Some(2), deIter.Rfind(func(x int) bool { return x == 2 }))

var b = []int{1, 2, 3}
var deIter2 = FromSlice(b).MustToDoubleEnded()
assert.Equal(t, option.None[int](), deIter2.Rfind(func(x int) bool { return x == 5 }))

func (DoubleEndedIterator[T]) Rfold

func (de DoubleEndedIterator[T]) Rfold(init T, f func(T, T) T) T

Rfold folds every element into an accumulator by applying an operation, starting from the back.

This is the reverse version of 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.

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.

Examples

var a = []int{1, 2, 3}
var deIter = FromSlice(a).MustToDoubleEnded()
var sum = deIter.Rfold(0, func(acc int, x int) int { return acc + x })
assert.Equal(t, 6, sum)

func (DoubleEndedIterator[T]) TryRfold

func (de DoubleEndedIterator[T]) TryRfold(init T, f func(T, T) result.Result[T]) result.Result[T]

TryRfold is the reverse version of TryFold: it takes elements starting from the back of the iterator.

Examples

var a = []string{"1", "2", "3"}
var deIter = FromSlice(a).MustToDoubleEnded()
var sum = deIter.TryRfold(0, func(acc int, s string) result.Result[int] {
	if v, err := strconv.Atoi(s); err == nil {
		return result.Ok(acc + v)
	}
	return result.TryErr[int](err)
})
assert.True(t, sum.IsOk())
assert.Equal(t, 6, sum.Unwrap())

func (DoubleEndedIterator[T]) XRfold

func (de DoubleEndedIterator[T]) XRfold(init any, f func(any, T) any) any

XRfold folds every element into an accumulator by applying an operation, starting from the back (any version).

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

Examples

var a = []int{1, 2, 3}
var deIter = FromSlice(a).MustToDoubleEnded()
var deIter = iterator.MustToDoubleEnded()
var sum = deIter.XRfold(0, func(acc any, x int) any { return acc.(int) + x })
assert.Equal(t, 6, sum)

func (DoubleEndedIterator[T]) XTryRfold

func (de DoubleEndedIterator[T]) XTryRfold(init any, f func(any, T) result.Result[any]) result.Result[any]

XTryRfold is the reverse version of TryFold: it takes elements starting from the back of the iterator (any version).

Examples

var a = []string{"1", "2", "3"}
var deIter = FromSlice(a).MustToDoubleEnded()
var sum = deIter.XTryRfold(0, func(acc any, s string) result.Result[any] {
	if v, err := strconv.Atoi(s); err == nil {
		return result.Ok(any(acc.(int) + v))
	}
	return result.TryErr[any](err)
})
assert.True(t, sum.IsOk())
assert.Equal(t, 6, sum.Unwrap().(int))

type Iterable

type Iterable[T any] interface {
	// Next returns the next value in the sequence.
	// Returns Some(value) if there is a next value, None otherwise.
	Next() option.Option[T]
	// SizeHint returns a hint about the remaining size of the sequence.
	// Returns (lower_bound, Some(upper_bound)) if the size is known,
	// or (lower_bound, None) if the upper bound is unknown.
	SizeHint() (uint, option.Option[uint])
}

Iterable represents a sequence of values that can be iterated over.

type IterableCount

type IterableCount interface {
	// Count returns the total number of elements.
	Count() uint
}

IterableCount represents an iterable that can count its elements.

type IterableSizeHint

type IterableSizeHint interface {
	// SizeHint returns a hint about the remaining size of the sequence.
	// Returns (lower_bound, Some(upper_bound)) if the size is known,
	// or (lower_bound, None) if the upper bound is unknown.
	SizeHint() (uint, option.Option[uint])
}

IterableSizeHint represents an iterable that can provide size hints.

type Iterator

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

Iterator is the main iterator type that provides method chaining. It wraps an Iterable[T] interface and provides all adapter methods as struct methods, enabling Rust-like method chaining: iterator.Map(...).Filter(...).Collect()

Iterator implements gust.Iterable[T] and gust.IterableSizeHint, so it can be used anywhere these interfaces are expected.

Examples

var iter = FromSlice([]int{1, 2, 3, 4, 5})
var result = iterator.Filter(func(x int) bool { return x > 2 }).
              Take(2).
              Collect()

func ArrayChunks

func ArrayChunks[T any](iter Iterator[T], chunkSize uint) Iterator[[]T]

ArrayChunks creates an iterator that yields chunks of a given size.

Panics

Panics if chunk_size is 0.

Examples

var iter = ArrayChunks(FromSlice([]int{1, 2, 3, 4, 5}), 2)
chunk1 := iterator.Next()
assert.True(t, chunk1.IsSome())
assert.Equal(t, []int{1, 2}, chunk1.Unwrap())

chunk2 := iterator.Next()
assert.True(t, chunk2.IsSome())
assert.Equal(t, []int{3, 4}, chunk2.Unwrap())

chunk3 := iterator.Next()
assert.True(t, chunk3.IsSome())
assert.Equal(t, []int{5}, chunk3.Unwrap()) // Last partial chunk

func ChunkBy

func ChunkBy[T any](iter Iterator[T], predicate func(T, T) bool) Iterator[[]T]

ChunkBy creates an iterator that groups consecutive elements that are equal according to the predicate function.

The predicate function receives two consecutive elements and should return true if they should be in the same group.

Examples

var iter = ChunkBy(FromSlice([]int{1, 1, 2, 2, 2, 3, 3}), func(a, b int) bool { return a == b })
chunk1 := iterator.Next()
assert.True(t, chunk1.IsSome())
assert.Equal(t, []int{1, 1}, chunk1.Unwrap())

chunk2 := iterator.Next()
assert.True(t, chunk2.IsSome())
assert.Equal(t, []int{2, 2, 2}, chunk2.Unwrap())

chunk3 := iterator.Next()
assert.True(t, chunk3.IsSome())
assert.Equal(t, []int{3, 3}, chunk3.Unwrap())

assert.True(t, iterator.Next().IsNone())

func Cloned

func Cloned[T any](iter Iterator[*T]) Iterator[T]

Cloned creates an iterator which clones all of its elements. This function accepts Iterator[*T] and returns Iterator[T] for chainable calls.

func Empty

func Empty[T any]() Iterator[T]

Empty creates an iterator that yields no values.

Examples

var iter = Empty[int]()
assert.Equal(t, option.None[int](), iterator.Next())

func Enumerate

func Enumerate[T any](iter Iterator[T]) Iterator[pair.Pair[uint, T]]

Enumerate creates an iterator that yields pairs of (index, value). This function accepts Iterator[T] and returns Iterator[pair.Pair[uint, T]] for chainable calls.

func FilterMap

func FilterMap[T any, U any](iter Iterator[T], f func(T) option.Option[U]) Iterator[U]

FilterMap creates an iterator that both filters and maps.

The returned iterator yields only the values for which the supplied closure returns option.Some(value).

FilterMap can be used to make chains of Filter and Map more concise. The example below shows how a Map().Filter().Map() can be shortened to a single call to FilterMap.

Examples

Basic usage:

var a = []string{"1", "two", "NaN", "four", "5"}
var iter = FilterMap(FromSlice(a), func(s string) option.Option[int] {
	if v, err := strconv.Atoi(s); err == nil {
		return option.Some(v)
	}
	return option.None[int]()
})

assert.Equal(t, option.Some(1), iterator.Next())
assert.Equal(t, option.Some(5), iterator.Next())
assert.Equal(t, option.None[int](), iterator.Next())

FilterMap creates an iterator that both filters and maps. This function accepts Iterator[T] and returns Iterator[U] for chainable calls.

func FlatMap

func FlatMap[T any, U any](iter Iterator[T], f func(T) Iterator[U]) Iterator[U]

FlatMap 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. FlatMap() will remove this extra layer on its own.

You can think of FlatMap(f) as the semantic equivalent of Mapping, and then Flattening as in Map(f).Flatten().

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

Examples

var words = []string{"alpha", "beta", "gamma"}
var iter = FlatMap(FromSlice(words), func(s string) Iterator[rune] {
	return FromSlice([]rune(s))
})
var result = Collect[rune](iter)
// result contains all characters from all words

func Flatten

func Flatten[T any](iter Iterator[Iterator[T]]) Iterator[T]

Flatten 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.

Examples

Basic usage:

var data = [][]int{{1, 2, 3, 4}, {5, 6}}
var iter = Flatten(FromSlice(data))
var result = Collect[int](iter)
// result is []int{1, 2, 3, 4, 5, 6}

func FromBitSet

func FromBitSet(bitset BitSetLike) Iterator[pair.Pair[int, bool]]

FromBitSet creates an iterator over all bits in a bit set, yielding pairs of (offset, bool) where offset is the bit position and bool indicates whether the bit is set.

Examples

// Assuming you have a BitSet implementation
type MyBitSet struct {
	bits []byte
}
func (b *MyBitSet) Size() int { return len(b.bits) * 8 }
func (b *MyBitSet) Get(offset int) bool {
	if offset < 0 || offset >= b.Size() {
		return false
	}
	byteIdx := offset / 8
	bitIdx := offset % 8
	return (b.bits[byteIdx] & (1 << (7 - bitIdx))) != 0
}

bitset := &MyBitSet{bits: []byte{0b10101010}}
iter := FromBitSet(bitset)
pair := iterator.Next()
assert.True(t, pair.IsSome())
assert.Equal(t, 0, pair.Unwrap().A)  // offset
assert.Equal(t, true, pair.Unwrap().B) // bit value

// Filter only set bits
setBits := FromBitSet(bitset).
	Filter(func(p pair.Pair[int, bool]) bool { return p.B }).
	Map(func(p pair.Pair[int, bool]) int { return p.A }).
	Collect()

func FromBitSetBytes

func FromBitSetBytes(bytes []byte) Iterator[pair.Pair[int, bool]]

FromBitSetBytes creates an iterator over all bits in a byte slice, treating the bytes as a bit set and yielding pairs of (offset, bool) where offset is the bit position (0-indexed from the first byte, first bit) and bool indicates whether the bit is set.

Bits are ordered from the most significant bit (MSB) to the least significant bit (LSB) within each byte, and bytes are ordered from first to last.

Examples

bytes := []byte{0b10101010, 0b11001100}
iter := FromBitSetBytes(bytes)
pair := iterator.Next()
assert.True(t, pair.IsSome())
assert.Equal(t, 0, pair.Unwrap().A)  // offset
assert.Equal(t, true, pair.Unwrap().B) // bit value (MSB of first byte)

// Get all set bit offsets
setBits := FromBitSetBytes(bytes).
	Filter(func(p pair.Pair[int, bool]) bool { return p.B }).
	Map(func(p pair.Pair[int, bool]) int { return p.A }).
	Collect()
// setBits contains [0, 2, 4, 6, 8, 9, 12, 13]

// Count set bits
count := FromBitSetBytes(bytes).
	Filter(func(p pair.Pair[int, bool]) bool { return p.B }).
	Count()

func FromBitSetBytesOnes

func FromBitSetBytesOnes(bytes []byte) Iterator[int]

FromBitSetBytesOnes creates an iterator over only the bits that are set to true (1) in a byte slice (treated as a bit set), yielding the offset of each set bit.

Examples

bytes := []byte{0b10101010, 0b11001100}
iter := FromBitSetBytesOnes(bytes)
assert.Equal(t, option.Some(0), iterator.Next())  // first set bit
assert.Equal(t, option.Some(2), iterator.Next())  // second set bit
assert.Equal(t, option.Some(4), iterator.Next())  // third set bit
// ... continues with all set bits

func FromBitSetBytesZeros

func FromBitSetBytesZeros(bytes []byte) Iterator[int]

FromBitSetBytesZeros creates an iterator over only the bits that are set to false (0) in a byte slice (treated as a bit set), yielding the offset of each unset bit.

Examples

bytes := []byte{0b10101010, 0b11001100}
iter := FromBitSetBytesZeros(bytes)
assert.Equal(t, option.Some(1), iterator.Next())  // first unset bit
assert.Equal(t, option.Some(3), iterator.Next())  // second unset bit
assert.Equal(t, option.Some(5), iterator.Next())  // third unset bit
// ... continues with all unset bits

func FromBitSetOnes

func FromBitSetOnes(bitset BitSetLike) Iterator[int]

FromBitSetOnes creates an iterator over only the bits that are set to true (1) in a bit set, yielding the offset of each set bit.

Examples

bitset := &MyBitSet{bits: []byte{0b10101010}}
iter := FromBitSetOnes(bitset)
assert.Equal(t, option.Some(0), iterator.Next())  // first set bit
assert.Equal(t, option.Some(2), iterator.Next())  // second set bit
assert.Equal(t, option.Some(4), iterator.Next())  // third set bit
assert.Equal(t, option.Some(6), iterator.Next())  // fourth set bit
assert.Equal(t, option.None[int](), iterator.Next())

// Chain with other iterator methods
sum := FromBitSetOnes(bitset).
	Filter(func(offset int) bool { return offset > 2 }).
	Fold(0, func(acc, offset int) int { return acc + offset })

func FromBitSetZeros

func FromBitSetZeros(bitset BitSetLike) Iterator[int]

FromBitSetZeros creates an iterator over only the bits that are set to false (0) in a bit set, yielding the offset of each unset bit.

Examples

bitset := &MyBitSet{bits: []byte{0b10101010}}
iter := FromBitSetZeros(bitset)
assert.Equal(t, option.Some(1), iterator.Next())  // first unset bit
assert.Equal(t, option.Some(3), iterator.Next())  // second unset bit
assert.Equal(t, option.Some(5), iterator.Next())  // third unset bit
assert.Equal(t, option.Some(7), iterator.Next())  // fourth unset bit
assert.Equal(t, option.None[int](), iterator.Next())

func FromElements

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

FromElements creates an iterator from a set of elements.

Examples

var iter = FromElements(1, 2, 3)
assert.Equal(t, option.Some(1), iterator.Next())
assert.Equal(t, option.Some(2), iterator.Next())
assert.Equal(t, option.Some(3), iterator.Next())
assert.Equal(t, option.None[int](), iterator.Next())

func FromFunc

func FromFunc[T any](f func() option.Option[T]) Iterator[T]

FromFunc creates an iterator from a function that generates values.

The function is called repeatedly until it returns option.None[T]().

Examples

var count = 0
var iter = FromFunc(func() option.Option[int] {
	if count < 3 {
		count++
		return option.Some(count)
	}
	return option.None[int]()
})
assert.Equal(t, option.Some(1), iterator.Next())
assert.Equal(t, option.Some(2), iterator.Next())
assert.Equal(t, option.Some(3), iterator.Next())
assert.Equal(t, option.None[int](), iterator.Next())

func FromIterable

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

FromIterable creates an iterator from a gust.Iterable[T]. If the data is already an Iterator[T], it returns the same iterator. If the data is an Iterable[T], it returns an Iterator[T] with the core. If the data is a gust.Iterable[T], it returns an Iterator[T] with the iterable wrapper.

Examples

var iter = FromIterable(FromSlice([]int{1, 2, 3}))
assert.Equal(t, option.Some(1), iterator.Next())
assert.Equal(t, option.Some(2), iterator.Next())
assert.Equal(t, option.Some(3), iterator.Next())
assert.Equal(t, option.None[int](), iterator.Next())

func FromPull

func FromPull[T any](next func() (T, bool), stop func()) (Iterator[T], func())

FromPull creates an Iterator[T] from a pull-style iterator (next and stop functions). This allows converting pull-style iterators to gust iterators. Returns the iterator and a deferStop function that should be deferred to ensure proper cleanup.

Note: While the sequence will automatically clean up when it ends naturally (when next() returns false), it is recommended to always use "defer deferStop()" to ensure proper cleanup in all cases, including early termination.

Examples

// Convert a pull-style iterator to gust Iterator
next, stop := iterator.Pull(someSeq)
defer stop()
gustIter, deferStop := FromPull(next, stop)
defer deferStop()
result := gustIter.Filter(func(x int) bool { return x > 2 }).Collect()

// Works with custom pull-style iterators
customNext := func() (int, bool) {
	// custom implementation
	return 0, false
}
customStop := func() {}
gustIter, deferStop = FromPull(customNext, customStop)
defer deferStop()

func FromPull2

func FromPull2[K any, V any](next func() (K, V, bool), stop func()) (Iterator[pair.Pair[K, V]], func())

FromPull2 creates an Iterator[pair.Pair[K, V]] from a pull-style iterator (next and stop functions). This allows converting pull-style key-value iterators to gust pair iterators. Returns the iterator and a deferStop function that should be deferred to ensure proper cleanup.

Note: While the sequence will automatically clean up when it ends naturally (when next() returns false), it is recommended to always use "defer deferStop()" to ensure proper cleanup in all cases, including early termination.

Examples

// Convert a pull-style iterator to gust Iterator
next, stop := iterator.Pull2(someSeq2)
defer stop()
gustIter, deferStop := FromPull2(next, stop)
defer deferStop()
result := gustIter.Filter(func(p pair.Pair[int, string]) bool {
	return p.B != ""
}).Collect()

// Works with custom pull-style iterators
customNext := func() (int, string, bool) {
	// custom implementation
	return 0, "", false
}
customStop := func() {}
gustIter, deferStop = FromPull2(customNext, customStop)
defer deferStop()

func FromRange

func FromRange[T constraints.Integer](start T, end T) Iterator[T]

FromRange creates an iterator from a range of integers.

The range is [start, end), meaning start is inclusive and end is exclusive.

Examples

var iter = FromRange(0, 5)
assert.Equal(t, option.Some(0), iterator.Next())
assert.Equal(t, option.Some(1), iterator.Next())
assert.Equal(t, option.Some(2), iterator.Next())
assert.Equal(t, option.Some(3), iterator.Next())
assert.Equal(t, option.Some(4), iterator.Next())
assert.Equal(t, option.None[int](), iterator.Next())

func FromSeq

func FromSeq[T any](seq iter.Seq[T]) (Iterator[T], func())

FromSeq creates an Iterator[T] from Go's standard iterator.Seq[T]. This allows converting Go standard iterators to gust iterators. Returns the iterator and a deferStop function that should be deferred to ensure proper cleanup.

Note: While the sequence will automatically clean up when it ends naturally (when next() returns false), it is recommended to always use "defer deferStop()" to ensure proper cleanup in all cases, including early termination.

Examples

// Convert a Go range iterator to gust Iterator
seq := func(yield func(int) bool) {
	for i := 0; i < 5; i++ {
		if !yield(i) {
			return
		}
	}
}
iter, deferStop := FromSeq(seq)
defer deferStop() // Recommended: ensures cleanup even if iteration ends naturally
assert.Equal(t, option.Some(0), iterator.Next())
assert.Equal(t, option.Some(1), iterator.Next())

// Works with Go's standard library iterators
iter, deferStop = FromSeq(iterator.N(5)) // iterator.N(5) returns iterator.Seq[int]
defer deferStop()
assert.Equal(t, option.Some(0), iterator.Next())

func FromSeq2

func FromSeq2[K any, V any](seq iter.Seq2[K, V]) (Iterator[pair.Pair[K, V]], func())

FromSeq2 creates an Iterator[pair.Pair[K, V]] from Go's standard iterator.Seq2[K, V]. This allows converting Go standard key-value iterators to gust pair iterators. Returns the iterator and a deferStop function that should be deferred to ensure proper cleanup.

Note: While the sequence will automatically clean up when it ends naturally (when next() returns false), it is recommended to always use "defer deferStop()" to ensure proper cleanup in all cases, including early termination.

Examples

// Convert a Go map iterator to gust Iterator
m := map[string]int{"a": 1, "b": 2, "c": 3}
seq2 := func(yield func(string, int) bool) {
	for k, v := range m {
		if !yield(k, v) {
			return
		}
	}
}
iter, deferStop := FromSeq2(seq2)
defer deferStop()
pair := iterator.Next()
assert.True(t, pair.IsSome())
assert.Contains(t, []string{"a", "b", "c"}, pair.Unwrap().A)

// Works with Go's standard library iterators
iter, deferStop = FromSeq2(maps.All(myMap)) // maps.All returns iterator.Seq2[K, V]
defer deferStop()

func FromSlice

func FromSlice[T any](slice []T) Iterator[T]

FromSlice creates an iterator from a slice.

The returned iterator supports double-ended iteration, allowing iteration from both ends. Use AsDoubleEnded() to convert to DoubleEndedIterator.

Examples

var a = []int{1, 2, 3}
var iter = FromSlice(a)
assert.Equal(t, option.Some(1), iterator.Next())
assert.Equal(t, option.Some(2), iterator.Next())
assert.Equal(t, option.Some(3), iterator.Next())
assert.Equal(t, option.None[int](), iterator.Next())

// As DoubleEndedIterator:
var deIter = AsDoubleEnded(FromSlice([]int{1, 2, 3, 4, 5, 6}))
assert.Equal(t, option.Some(1), deIter.Next())
assert.Equal(t, option.Some(6), deIter.NextBack())
assert.Equal(t, option.Some(5), deIter.NextBack())

func Map

func Map[T any, U any](iter Iterator[T], f func(T) U) Iterator[U]

Map creates an iterator which calls a closure on each element.

Map() transforms one iterator into another, by means of its argument: something that implements a function. It produces a new iterator which calls this closure on each element of the original iterator.

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

Map() is conceptually similar to a for loop. However, as Map() 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 Map().

Examples

Basic usage:

var a = []int{1, 2, 3}
var iter = Map(FromSlice(a), func(x int) int { return 2 * x })

assert.Equal(t, option.Some(2), iterator.Next())
assert.Equal(t, option.Some(4), iterator.Next())
assert.Equal(t, option.Some(6), iterator.Next())
assert.Equal(t, option.None[int](), iterator.Next())

Map creates an iterator which calls a closure on each element. This function accepts Iterator[T] and returns Iterator[U] for chainable calls.

func MapWhile

func MapWhile[T any, U any](iter Iterator[T], predicate func(T) option.Option[U]) Iterator[U]

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

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

Examples

Basic usage:

var a = []int{-1, 4, 0, 1}
var iter = MapWhile(FromSlice(a), func(x int) option.Option[int] {
	if x != 0 {
		return option.Some(16 / x)
	}
	return option.None[int]()
})

assert.Equal(t, option.Some(-16), iterator.Next())
assert.Equal(t, option.Some(4), iterator.Next())
assert.Equal(t, option.None[int](), iterator.Next())

func MapWindows

func MapWindows[T any, U any](iter Iterator[T], windowSize uint, f func([]T) U) Iterator[U]

MapWindows creates an iterator that applies a function to overlapping windows of a given size.

The windows are arrays of a fixed size that overlap. The first window contains the first N elements, the second window contains elements [1..N+1], etc.

Panics

Panics if window_size is 0 or if the iterator has fewer than window_size elements.

Examples

var iter = MapWindows(FromSlice([]int{1, 2, 3, 4, 5}), 3, func(window []int) int {
	return window[0] + window[1] + window[2]
})
assert.Equal(t, option.Some(6), iterator.Next())  // 1+2+3
assert.Equal(t, option.Some(9), iterator.Next())  // 2+3+4
assert.Equal(t, option.Some(12), iterator.Next()) // 3+4+5
assert.Equal(t, option.None[int](), iterator.Next())

func Once

func Once[T any](value T) Iterator[T]

Once creates an iterator that yields a single value.

Examples

Once creates an iterator that yields a value exactly once.

Examples

var iter = Once(42)
assert.Equal(t, option.Some(42), iterator.Next())
assert.Equal(t, option.None[int](), iterator.Next())

func OptMap

func OptMap[T any, U any](iter Iterator[T], f func(T) *U) Iterator[option.Option[*U]]

OptMap creates an iterator which calls a closure on each element and returns a Option[*U]. NOTE:

`non-nil pointer` is wrapped as Some,
and `nil pointer` is wrapped as None.

Examples

iter := OptMap(FromSlice([]string{"1", "2", "3", "NaN"}), func(s string) *int {
	if v, err := strconv.Atoi(s); err == nil {
		return &v
	} else {
		return nil
	}
})

var newInt = func(v int) *int {
	return &v
}

assert.Equal(t, option.Some(option.Some(newInt(1))), iterator.Next()) assert.Equal(t, option.Some(option.Some(newInt(2))), iterator.Next()) assert.Equal(t, option.Some(option.Some(newInt(3))), iterator.Next()) assert.Equal(t, option.Some(option.None[*int]()), iterator.Next()) assert.Equal(t, option.None[option.Option[*int]](), iterator.Next())

func Repeat

func Repeat[T any](value T) Iterator[T]

Repeat creates an iterator that repeats a value endlessly.

Examples

var iter = Repeat(42)
assert.Equal(t, option.Some(42), iterator.Next())
assert.Equal(t, option.Some(42), iterator.Next())
assert.Equal(t, option.Some(42), iterator.Next())
// ... continues forever

func RetMap

func RetMap[T any, U any](iter Iterator[T], f func(T) (U, error)) Iterator[result.Result[U]]

RetMap creates an iterator which calls a closure on each element and returns a Result[U].

Examples

iter := RetMap(FromSlice([]string{"1", "2", "3", "NaN"}), strconv.Atoi)

assert.Equal(t, option.Some(result.Ok(1)), iterator.Next()) assert.Equal(t, option.Some(result.Ok(2)), iterator.Next()) assert.Equal(t, option.Some(result.Ok(3)), iterator.Next()) assert.Equal(t, true, iterator.Next().Unwrap().IsErr()) assert.Equal(t, option.None[result.Result[int]](), iterator.Next())

func Scan

func Scan[T any, U any, St any](iter Iterator[T], initialState St, f func(*St, T) option.Option[U]) Iterator[U]

Scan is an iterator adapter which, like Fold, holds internal state, but unlike Fold, produces a new iterator.

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 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.Option, is returned by the Next() method. Thus the closure can return option.Some(value) to yield value, or option.None[T]() to end the iteration.

Examples

var a = []int{1, 2, 3, 4}
var iter = Scan(FromSlice(a), 1, func(state *int, x int) option.Option[int] {
	*state = *state * x
	if *state > 6 {
		return option.None[int]()
	}
	return option.Some(-*state)
})

assert.Equal(t, option.Some(-1), iterator.Next())
assert.Equal(t, option.Some(-2), iterator.Next())
assert.Equal(t, option.Some(-6), iterator.Next())
assert.Equal(t, option.None[int](), iterator.Next())

func Zip

func Zip[T any, U any](a Iterator[T], b Iterator[U]) Iterator[pair.Pair[T, U]]

Zip '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 option.None[T](), Next() from the zipped iterator will return option.None[T]().

Examples

Basic usage:

var s1 = FromSlice([]rune{'a', 'b', 'c'})
var s2 = FromSlice([]rune{'d', 'e', 'f'})
var iter = Zip(s1, s2)

assert.Equal(t, option.Some(pair.Pair[rune, rune]{A: 'a', B: 'd'}), iterator.Next())
assert.Equal(t, option.Some(pair.Pair[rune, rune]{A: 'b', B: 'e'}), iterator.Next())
assert.Equal(t, option.Some(pair.Pair[rune, rune]{A: 'c', B: 'f'}), iterator.Next())
assert.Equal(t, option.None[pair.Pair[rune, rune]](), iterator.Next())

Zip creates an iterator that zips two iterators together. This function accepts Iterator[T] and Iterator[U] and returns Iterator[pair.Pair[T, U]] for chainable calls.

func (Iterator[T]) AdvanceBy

func (it Iterator[T]) AdvanceBy(n uint) result.VoidResult

AdvanceBy advances the iterator by n elements.

Examples

var iter = FromSlice([]int{1, 2, 3, 4})
assert.True(t, iterator.AdvanceBy(2).IsOk())

func (Iterator[T]) All

func (it Iterator[T]) All(predicate func(T) bool) bool

All tests if all elements satisfy a predicate.

Examples

var iter = FromSlice([]int{2, 4, 6})
assert.True(t, iterator.All(func(x int) bool { return x%2 == 0 }))

func (Iterator[T]) Any

func (it Iterator[T]) Any(predicate func(T) bool) bool

Any tests if any element satisfies a predicate.

Examples

var iter = FromSlice([]int{1, 2, 3})
assert.True(t, iterator.Any(func(x int) bool { return x > 2 }))

func (Iterator[T]) Chain

func (it Iterator[T]) Chain(other Iterator[T]) Iterator[T]

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

Examples

var iter1 = FromSlice([]int{1, 2, 3})
var iter2 = FromSlice([]int{4, 5, 6})
var chained = iter1.Chain(iter2)
assert.Equal(t, option.Some(1), chained.Next())

func (Iterator[T]) Collect

func (it Iterator[T]) Collect() []T

Collect collects all items into a slice.

Examples

var iter = FromSlice([]int{1, 2, 3})
var result = iterator.Collect()
assert.Equal(t, []int{1, 2, 3}, result)

func (Iterator[T]) Count

func (it Iterator[T]) Count() uint

Count consumes the iterator, counting the number of iterations.

Examples

var iter = FromSlice([]int{1, 2, 3, 4, 5})
assert.Equal(t, uint(5), iterator.Count())

func (Iterator[T]) Cycle

func (it Iterator[T]) Cycle() Iterator[T]

Cycle repeats an iterator endlessly.

Examples

var iter = FromSlice([]int{1, 2, 3})
var cycled = iterator.Cycle()
assert.Equal(t, option.Some(1), cycled.Next())
assert.Equal(t, option.Some(2), cycled.Next())
assert.Equal(t, option.Some(3), cycled.Next())
assert.Equal(t, option.Some(1), cycled.Next()) // starts over

func (Iterator[T]) Filter

func (it Iterator[T]) Filter(predicate func(T) bool) Iterator[T]

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

Examples

var iter = FromSlice([]int{0, 1, 2})
var filtered = iterator.Filter(func(x int) bool { return x > 0 })
assert.Equal(t, option.Some(1), filtered.Next())

func (Iterator[T]) FilterMap

func (it Iterator[T]) FilterMap(f func(T) option.Option[T]) Iterator[T]

FilterMap creates an iterator that both filters and maps.

Examples

var iter = FromSlice([]string{"1", "two", "NaN", "four", "5"})
var filtered = iterator.FilterMap(func(s string) option.Option[string] {
	if s == "1" || s == "5" {
		return option.Some(s)
	}
	return option.None[string]()
})
// Can chain: filtered.Filter(...).Collect()

func (Iterator[T]) Find

func (it Iterator[T]) Find(predicate func(T) bool) option.Option[T]

Find searches for an element that satisfies a predicate.

Examples

var iter = FromSlice([]int{1, 2, 3})
assert.Equal(t, option.Some(2), iterator.Find(func(x int) bool { return x > 1 }))

func (Iterator[T]) FindMap

func (it Iterator[T]) FindMap(f func(T) option.Option[T]) option.Option[T]

FindMap searches for an element and maps it.

Examples

var iter = FromSlice([]string{"lol", "NaN", "2", "5"})
var firstNumber = iterator.FindMap(func(s string) option.Option[int] {
	if v, err := strconv.Atoi(s); err == nil {
		return option.Some(v)
	}
	return option.None[int]()
})
assert.Equal(t, option.Some(2), firstNumber)

func (Iterator[T]) FlatMap

func (it Iterator[T]) FlatMap(f func(T) Iterator[T]) Iterator[T]

FlatMap creates an iterator that maps and flattens nested iterators.

Examples

var iter = FromSlice([]int{1, 2, 3})
var flatMapped = iterator.FlatMap(func(x int) Iterator[int] {
	return FromSlice([]int{x, x * 2})
})
// Can chain: flatMapped.Filter(...).Collect()

func (Iterator[T]) Fold

func (it Iterator[T]) Fold(init T, f func(T, T) T) T

Fold folds every element into an accumulator. This wrapper method allows Fold to be called as a method.

Examples

var iter = FromSlice([]int{1, 2, 3})
var sum = iterator.Fold(0, func(acc int, x int) int { return acc + x })
assert.Equal(t, 6, sum)

func (Iterator[T]) ForEach

func (it Iterator[T]) ForEach(f func(T))

ForEach calls a closure on each element.

Examples

var iter = FromSlice([]int{1, 2, 3})
iterator.ForEach(func(x int) { fmt.Println(x) })

func (Iterator[T]) Fuse

func (it Iterator[T]) Fuse() Iterator[T]

Fuse creates an iterator that ends after the first None.

Examples

var iter = FromSlice([]int{1, 2, 3})
var fused = iterator.Fuse()
// After None, it will always return None

func (Iterator[T]) Inspect

func (it Iterator[T]) Inspect(f func(T)) Iterator[T]

Inspect creates an iterator that calls a closure on each element for side effects.

Examples

var iter = FromSlice([]int{1, 2, 3})
var inspected = iterator.Inspect(func(x int) { fmt.Println(x) })
// Prints 1, 2, 3 when iterated

func (Iterator[T]) Intersperse

func (it Iterator[T]) Intersperse(separator T) Iterator[T]

Intersperse creates an iterator that places a separator between adjacent items.

Examples

var iter = FromSlice([]int{0, 1, 2})
var interspersed = iterator.Intersperse(100)
assert.Equal(t, option.Some(0), interspersed.Next())
assert.Equal(t, option.Some(100), interspersed.Next())

func (Iterator[T]) IntersperseWith

func (it Iterator[T]) IntersperseWith(separator func() T) Iterator[T]

IntersperseWith creates an iterator that places an item generated by separator between adjacent items.

Examples

var iter = FromSlice([]int{0, 1, 2})
var interspersed = iterator.IntersperseWith(func() int { return 99 })
assert.Equal(t, option.Some(0), interspersed.Next())
assert.Equal(t, option.Some(99), interspersed.Next())

func (Iterator[T]) Last

func (it Iterator[T]) Last() option.Option[T]

Last returns the last element of the iterator.

Examples

var iter = FromSlice([]int{1, 2, 3})
assert.Equal(t, option.Some(3), iterator.Last())

func (Iterator[T]) Map

func (it Iterator[T]) Map(f func(T) T) Iterator[T]

Map creates an iterator which calls a closure on each element.

Examples

var iter = FromSlice([]int{1, 2, 3})
var doubled = iterator.Map(func(x int) int { return x * 2 })
assert.Equal(t, option.Some(2), doubled.Next())
// Can chain: doubled.Filter(...).Collect()

func (Iterator[T]) MapWhile

func (it Iterator[T]) MapWhile(predicate func(T) option.Option[T]) Iterator[T]

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

func (Iterator[T]) MapWindows

func (it Iterator[T]) MapWindows(windowSize uint, f func([]T) T) Iterator[T]

MapWindows creates an iterator that applies a function to overlapping windows.

Examples

var iter = FromSlice([]int{1, 2, 3, 4, 5})
var windows = iterator.MapWindows(3, func(window []int) int {
	return window[0] + window[1] + window[2]
})
// Can chain: windows.Filter(...).Collect()

func (Iterator[T]) MaxBy

func (it Iterator[T]) MaxBy(compare func(T, T) int) option.Option[T]

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

Examples

var iter = FromSlice([]int{-3, 0, 1, 5, -10})
var max = iterator.MaxBy(func(x, y int) int {
	if x < y {
		return -1
	}
	if x > y {
		return 1
	}
	return 0
})
assert.Equal(t, option.Some(5), max)

func (Iterator[T]) MinBy

func (it Iterator[T]) MinBy(compare func(T, T) int) option.Option[T]

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

Examples

var iter = FromSlice([]int{-3, 0, 1, 5, -10})
var min = iterator.MinBy(func(x, y int) int {
	if x < y {
		return -1
	}
	if x > y {
		return 1
	}
	return 0
})
assert.Equal(t, option.Some(-10), min)

func (Iterator[T]) MustToDoubleEnded

func (it Iterator[T]) MustToDoubleEnded() DoubleEndedIterator[T]

MustToDoubleEnded converts to a DoubleEndedIterator[T] if the underlying iterator supports double-ended iteration. Otherwise, it panics.

Examples

var iter = FromSlice([]int{1, 2, 3})
var deIter = iterator.MustToDoubleEnded()
assert.Equal(t, option.Some(3), deIter.NextBack())
// Can use Iterator methods:
var doubled = deIter.Map(func(x int) any { return x * 2 })

func (Iterator[T]) Next

func (it Iterator[T]) Next() option.Option[T]

Next advances the iterator and returns the next value. This implements gust.Iterable[T] interface.

func (Iterator[T]) NextChunk

func (it Iterator[T]) NextChunk(n uint) ChunkResult[[]T]

NextChunk advances the iterator and returns an array containing the next N values.

Examples

var iter = FromSlice([]int{1, 2, 3, 4, 5})
chunk := iterator.NextChunk(2)
assert.True(t, chunk.IsOk())

func (Iterator[T]) Nth

func (it Iterator[T]) Nth(n uint) option.Option[T]

Nth returns the nth element of the iterator.

Examples

var iter = FromSlice([]int{1, 2, 3})
assert.Equal(t, option.Some(2), iterator.Nth(1))

func (Iterator[T]) Partition

func (it Iterator[T]) Partition(f func(T) bool) (truePart []T, falsePart []T)

Partition partitions the iterator into two slices.

Examples

var iter = FromSlice([]int{1, 2, 3, 4, 5})
evens, odds := iterator.Partition(func(x int) bool { return x%2 == 0 })
assert.Equal(t, []int{2, 4}, evens)
assert.Equal(t, []int{1, 3, 5}, odds)

func (Iterator[T]) Peekable

func (it Iterator[T]) Peekable() PeekableIterator[T]

func (Iterator[T]) Position

func (it Iterator[T]) Position(predicate func(T) bool) option.Option[uint]

Position searches for an element in an iterator, returning its index.

Examples

var iter = FromSlice([]int{1, 2, 3})
assert.Equal(t, option.Some(uint(1)), iterator.Position(func(x int) bool { return x == 2 }))

func (Iterator[T]) Pull

func (it Iterator[T]) Pull() (next func() (T, bool), stop func())

Pull converts the Iterator[T] to a pull-style iterator using Go's standard iterator.Pull. This returns two functions: next (to pull values) and stop (to stop iteration). The caller should defer stop() to ensure proper cleanup.

Examples

iter := FromSlice([]int{1, 2, 3, 4, 5})
next, stop := iterator.Pull()
defer stop()

// Pull values manually
for {
	v, ok := next()
	if !ok {
		break
	}
	fmt.Println(v)
	if v == 3 {
		break // Early termination
	}
}

func (Iterator[T]) Pull2

func (it Iterator[T]) Pull2() (next func() (uint, T, bool), stop func())

Pull2 converts the Iterator[T] to a pull-style iterator using Go's standard iterator.Pull2. This returns two functions: next (to pull key-value pairs) and stop (to stop iteration). The caller should defer stop() to ensure proper cleanup.

Examples

iter := FromSlice([]int{1, 2, 3, 4, 5})
next, stop := iterator.Pull2()
defer stop()

// Pull key-value pairs manually
for {
	k, v, ok := next()
	if !ok {
		break
	}
	fmt.Println(k, v)
	if v == 3 {
		break // Early termination
	}
}

func (Iterator[T]) Reduce

func (it Iterator[T]) Reduce(f func(T, T) T) option.Option[T]

Reduce reduces the iterator to a single value.

Examples

var iter = FromSlice([]int{1, 2, 3})
var sum = iterator.Reduce(func(acc int, x int) int { return acc + x })
assert.Equal(t, option.Some(6), sum)

func (Iterator[T]) Scan

func (it Iterator[T]) Scan(initialState T, f func(*T, T) option.Option[T]) Iterator[T]

Scan creates an iterator that scans over the iterator with a state.

Examples

var iter = FromSlice([]int{1, 2, 3})
var scanned = iterator.Scan(0, func(state *int, x int) option.Option[int] {
	*state = *state + x
	return option.Some(*state)
})
// Can chain: scanned.Filter(...).Collect()

func (Iterator[T]) Seq

func (it Iterator[T]) Seq() iter.Seq[T]

Seq converts the Iterator[T] to Go's standard iterator.Seq[T]. This allows using gust iterators with Go's built-in iteration support (for loops).

Examples

iter := FromSlice([]int{1, 2, 3})
for v := range iterator.Seq() {
	fmt.Println(v) // prints 1, 2, 3
}

func (Iterator[T]) Seq2

func (it Iterator[T]) Seq2() iter.Seq2[uint, T]

Seq2 converts the Iterator[T] to Go's standard iterator.Seq2[T]. This allows using gust iterators with Go's built-in iteration support (for loops).

Examples

iter := FromSlice([]int{1, 2, 3})

for k, v := range iterator.Seq2() {
	fmt.Println(k, v) // prints 0 1, 1 2, 2 3
}

func (Iterator[T]) SizeHint

func (it Iterator[T]) SizeHint() (uint, option.Option[uint])

SizeHint returns the bounds on the remaining length of the iterator. This implements gust.IterableSizeHint interface.

func (Iterator[T]) Skip

func (it Iterator[T]) Skip(n uint) Iterator[T]

Skip creates an iterator that skips the first n elements.

Examples

var iter = FromSlice([]int{1, 2, 3})
var skipped = iterator.Skip(2)
assert.Equal(t, option.Some(3), skipped.Next())

func (Iterator[T]) SkipWhile

func (it Iterator[T]) SkipWhile(predicate func(T) bool) Iterator[T]

SkipWhile creates an iterator that skips elements while predicate returns true.

Examples

var iter = FromSlice([]int{-1, 0, 1})
var skipped = iterator.SkipWhile(func(x int) bool { return x < 0 })
assert.Equal(t, option.Some(0), skipped.Next())

func (Iterator[T]) StepBy

func (it Iterator[T]) StepBy(step uint) Iterator[T]

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

Panics

Panics if step is 0.

Examples

var iter = FromSlice([]int{0, 1, 2, 3, 4, 5})
var stepped = iterator.StepBy(2)
assert.Equal(t, option.Some(0), stepped.Next())
assert.Equal(t, option.Some(2), stepped.Next())
assert.Equal(t, option.Some(4), stepped.Next())

func (Iterator[T]) Take

func (it Iterator[T]) Take(n uint) Iterator[T]

Take creates an iterator that yields the first n elements.

Examples

var iter = FromSlice([]int{1, 2, 3})
var taken = iterator.Take(2)
assert.Equal(t, option.Some(1), taken.Next())
assert.Equal(t, option.Some(2), taken.Next())
assert.Equal(t, option.None[int](), taken.Next())

func (Iterator[T]) TakeWhile

func (it Iterator[T]) TakeWhile(predicate func(T) bool) Iterator[T]

TakeWhile creates an iterator that yields elements while predicate returns true.

Examples

var iter = FromSlice([]int{-1, 0, 1})
var taken = iterator.TakeWhile(func(x int) bool { return x < 0 })
assert.Equal(t, option.Some(-1), taken.Next())
assert.Equal(t, option.None[int](), taken.Next())

func (Iterator[T]) TryFind

func (it Iterator[T]) TryFind(f func(T) result.Result[bool]) result.Result[option.Option[T]]

TryFind applies function to the elements of iterator and returns the first true result or the first error.

This is the fallible version of Find().

Examples

var a = []string{"1", "2", "lol", "NaN", "5"}
var res = iterator.TryFind(func(s string) result.Result[bool] {
	if s == "lol" {
		return result.TryErr[bool](errors.New("invalid"))
	}
	if v, err := strconv.Atoi(s); err == nil {
		return result.Ok(v == 2)
	}
	return result.Ok(false)
})
assert.True(t, result.IsOk())

func (Iterator[T]) TryFold

func (it Iterator[T]) TryFold(init T, f func(T, T) result.Result[T]) result.Result[T]

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

Examples

var iter = FromSlice([]int{1, 2, 3})
var sum = iterator.TryFold(0, func(acc int, x int) result.Result[int] {
	return result.Ok(acc + x)
})
assert.True(t, sum.IsOk())
assert.Equal(t, 6, sum.Unwrap())

func (Iterator[T]) TryForEach

func (it Iterator[T]) TryForEach(f func(T) result.Result[T]) result.Result[T]

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

Examples

var data = []string{"no_tea.txt", "stale_bread.json", "torrential_rain.png"}
var res = iterator.TryForEach(func(x string) result.Result[string] {
	fmt.Println(x)
	return result.Ok[string](x+"_processed")
})
assert.True(t, res.IsOk())
assert.Equal(t, "no_tea.txt_processed", res.Unwrap())

func (Iterator[T]) TryReduce

func (it Iterator[T]) TryReduce(f func(T, T) result.Result[T]) result.Result[option.Option[T]]

TryReduce reduces the elements to a single one by repeatedly applying a reducing operation.

Examples

var numbers = []int{10, 20, 5, 23, 0}
var sum = iterator.TryReduce(func(x, y int) result.Result[int] {
	if x+y > 100 {
		return result.TryErr[int](errors.New("overflow"))
	}
	return result.Ok(x + y)
})
assert.True(t, sum.IsOk())

func (Iterator[T]) TryToDoubleEnded

func (it Iterator[T]) TryToDoubleEnded() option.Option[DoubleEndedIterator[T]]

TryToDoubleEnded converts to a DoubleEndedIterator[T] if the underlying iterator supports double-ended iteration. Otherwise, it returns None.

Examples

var iter = FromSlice([]int{1, 2, 3})
var deIter = iterator.TryToDoubleEnded()
assert.Equal(t, option.Some(3), deIter.NextBack())
// Can use Iterator methods:
var doubled = deIter.Map(func(x int) any { return x * 2 })

func (Iterator[T]) XFilterMap

func (it Iterator[T]) XFilterMap(f func(T) option.Option[any]) Iterator[any]

XFilterMap creates an iterator that both filters and maps (any version).

Examples

var iter = FromSlice([]string{"1", "two", "NaN", "four", "5"})
var filtered = iterator.XFilterMap(func(s string) option.Option[any] {
	if s == "1" {
		return option.Some(any(1))
	}
	if s == "5" {
		return option.Some(any(5))
	}
	return option.None[any]()
})
// Can chain: filtered.Filter(...).Collect()

func (Iterator[T]) XFindMap

func (it Iterator[T]) XFindMap(f func(T) option.Option[any]) option.Option[any]

XFindMap searches for an element and maps it (any version).

Examples

var iter = FromSlice([]string{"lol", "NaN", "2", "5"})
var firstNumber = iterator.XFindMap(func(s string) option.Option[any] {
	if v, err := strconv.Atoi(s); err == nil {
		return option.Some(any(v))
	}
	return option.None[any]()
})
assert.True(t, firstNumber.IsSome())
assert.Equal(t, 2, firstNumber.Unwrap().(int))

func (Iterator[T]) XFlatMap

func (it Iterator[T]) XFlatMap(f func(T) Iterator[any]) Iterator[any]

XFlatMap creates an iterator that maps and flattens nested iterators (any version).

Examples

var iter = FromSlice([]int{1, 2, 3})
var flatMapped = iterator.XFlatMap(func(x int) Iterator[any] {
	return FromSlice([]any{x, x * 2})
})
// Can chain: flatMapped.Filter(...).Collect()

func (Iterator[T]) XFold

func (it Iterator[T]) XFold(init any, f func(any, T) any) any

XFold folds every element into an accumulator. This wrapper method allows XFold to be called as a method.

Examples

var iter = FromSlice([]int{1, 2, 3})
var sum = iterator.XFold(0, func(acc any, x int) any { return acc.(int) + x })
assert.Equal(t, 6, sum)

func (Iterator[T]) XMap

func (it Iterator[T]) XMap(f func(T) any) Iterator[any]

XMap creates an iterator which calls a closure on each element (any version).

Examples

var iter = FromSlice([]int{1, 2, 3})
var doubled = iterator.XMap(func(x int) any { return x * 2 })
assert.Equal(t, option.Some(2), doubled.Next())
// Can chain: doubled.Filter(...).Collect()

func (Iterator[T]) XMapWhile

func (it Iterator[T]) XMapWhile(predicate func(T) option.Option[any]) Iterator[any]

XMapWhile creates an iterator that both yields elements based on a predicate and maps (any version).

func (Iterator[T]) XMapWindows

func (it Iterator[T]) XMapWindows(windowSize uint, f func([]T) any) Iterator[any]

XMapWindows creates an iterator that applies a function to overlapping windows (any version).

Examples

var iter = FromSlice([]int{1, 2, 3, 4, 5})
var windows = iterator.XMapWindows(3, func(window []int) any {
	return window[0] + window[1] + window[2]
})
// Can chain: windows.Filter(...).Collect()

func (Iterator[T]) XScan

func (it Iterator[T]) XScan(initialState any, f func(*any, T) option.Option[any]) Iterator[any]

XScan creates an iterator that scans over the iterator with a state (any version).

Examples

var iter = FromSlice([]int{1, 2, 3})
var scanned = iterator.XScan(0, func(state *any, x int) option.Option[any] {
	s := (*state).(int) + x
	*state = s
	return option.Some(any(s))
})
// Can chain: scanned.Filter(...).Collect()

func (Iterator[T]) XTryFold

func (it Iterator[T]) XTryFold(init any, f func(any, T) result.Result[any]) result.Result[any]

XTryFold applies a function as long as it returns successfully, producing a single, final value (any version).

Examples

var iter = FromSlice([]int{1, 2, 3})
var sum = iterator.XTryFold(0, func(acc any, x int) result.Result[any] {
	return result.Ok[any](any(acc.(int) + x))
})
assert.True(t, sum.IsOk())
assert.Equal(t, 6, sum.Unwrap().(int))

func (Iterator[T]) XTryForEach

func (it Iterator[T]) XTryForEach(f func(T) result.Result[any]) result.Result[any]

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

Examples

var data = []string{"no_tea.txt", "stale_bread.json", "torrential_rain.png"}
var res = iterator.TryForEach(func(x string) result.Result[any] {
	fmt.Println(x)
	return result.Ok[any](nil)
})
assert.True(t, res.IsOk())

type PeekableIterator

type PeekableIterator[T any] struct {
	Iterator[T] // Embed Iterator to inherit all its methods
	// contains filtered or unexported fields
}

Peekable creates a peekable iterator.

Examples

var iter = FromSlice([]int{1, 2, 3})
var peekable = iterator.Peekable()
assert.Equal(t, option.Some(1), peekable.Peek())
assert.Equal(t, option.Some(1), peekable.Next())

// Can use all Iterator methods:
var filtered = peekable.Filter(func(x int) bool { return x > 1 })
assert.Equal(t, option.Some(2), filtered.Next())

PeekableIterator is an iterator that supports peeking at the next element. It embeds Iterator[T] to inherit all Iterator methods, and adds Peek() method.

Examples

var xs = []int{1, 2, 3}
var iter = Peekable(FromSlice(xs))

// peek() lets us see into the future
assert.Equal(t, option.Some(1), iterator.Peek())
assert.Equal(t, option.Some(1), iterator.Next())

// Can use all Iterator methods:
var filtered = iterator.Filter(func(x int) bool { return x > 1 })
assert.Equal(t, option.Some(2), filtered.Next())

func (*PeekableIterator[T]) Next

func (p *PeekableIterator[T]) Next() option.Option[T]

Next advances the iterator and returns the next value. This overrides Iterator[T].Next() to handle peeked values.

func (*PeekableIterator[T]) Peek

func (p *PeekableIterator[T]) Peek() option.Option[T]

Peek returns the next element without consuming it.

Examples

var xs = []int{1, 2, 3}
var iter = Peekable(FromSlice(xs))

assert.Equal(t, option.Some(1), iterator.Peek())
assert.Equal(t, option.Some(1), iterator.Peek()) // Can peek multiple times
assert.Equal(t, option.Some(1), iterator.Next())

func (*PeekableIterator[T]) SizeHint

func (p *PeekableIterator[T]) SizeHint() (uint, option.Option[uint])

SizeHint returns the bounds on the remaining length of the iterator. This overrides Iterator[T].SizeHint() to account for peeked values.

type SizeIterable

type SizeIterable[T any] interface {
	Iterable[T]
	// Remaining returns the number of remaining elements.
	Remaining() uint
}

SizeIterable represents an iterable that knows its remaining size.

Jump to

Keyboard shortcuts

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