Documentation
¶
Overview ¶
Package iterx provides composable, lazy iterator adapters for Go 1.23+.
It works with the standard iter.Seq and iter.Seq2 types and is fully compatible with the stdlib slices, maps, and iter packages.
All adapter functions are lazy: they return a new iterator without consuming the source, so work is only done when the result is ranged over or collected.
Free functions vs Chain ¶
Adapters that change the element type (Map, FlatMap) are free functions because Go methods cannot introduce new type parameters. Adapters that preserve the element type are also available as methods on Chain for convenient call chaining:
results := iterx.From(slices.Values(items)).
Filter(isActive).
Take(10).
Collect()
Mix free functions and Chain.Seq when a type-changing step is needed:
names := iterx.From(
iterx.Map(
iterx.From(slices.Values(users)).Filter(isActive).Seq(),
func(u User) string { return u.Name },
),
)
Sources ¶
Of, Range, RangeStep, Repeat, RepeatN, and Generate produce iterators from literal values or arithmetic, without requiring a slice or map. Use slices.Values and maps.All from the stdlib for existing collections.
Seq2 helpers ¶
Keys, Values, CollectMap, Filter2, Map2, and Swap operate on iter.Seq2 (two-value iterators such as those produced by maps.All or Zip).
Numeric helpers ¶
Sum, Min, Max, MinBy, and MaxBy work on numeric or ordered sequences.
Panics ¶
Functions that accept a size or step parameter (Chunk, Window, StepBy, RangeStep) panic immediately — before returning the iterator — when given an invalid argument. This surfaces programmer errors at the call site rather than lazily during iteration.
Index ¶
- func All[V any](seq iter.Seq[V], f func(V) bool) bool
- func Any[V any](seq iter.Seq[V], f func(V) bool) bool
- func Chunk[V any](seq iter.Seq[V], n int) iter.Seq[[]V]
- func Collect[V any](seq iter.Seq[V]) []V
- func CollectMap[K comparable, V any](seq iter.Seq2[K, V]) map[K]V
- func Concat[V any](seqs ...iter.Seq[V]) iter.Seq[V]
- func Count[V any](seq iter.Seq[V]) int
- func Drop[V any](seq iter.Seq[V], n int) iter.Seq[V]
- func DropWhile[V any](seq iter.Seq[V], f func(V) bool) iter.Seq[V]
- func Empty[V any]() iter.Seq[V]
- func Enumerate[V any](seq iter.Seq[V]) iter.Seq2[int, V]
- func Filter[V any](seq iter.Seq[V], f func(V) bool) iter.Seq[V]
- func Filter2[K, V any](seq iter.Seq2[K, V], f func(K, V) bool) iter.Seq2[K, V]
- func First[V any](seq iter.Seq[V]) (v V, ok bool)
- func FlatMap[In, Out any](seq iter.Seq[In], f func(In) iter.Seq[Out]) iter.Seq[Out]
- func Flatten[V any](seq iter.Seq[iter.Seq[V]]) iter.Seq[V]
- func ForEach[V any](seq iter.Seq[V], f func(V))
- func Generate[V any](seed V, next func(V) V) iter.Seq[V]
- func GroupBy[K comparable, V any](seq iter.Seq[V], key func(V) K) map[K][]V
- func Keys[K, V any](seq iter.Seq2[K, V]) iter.Seq[K]
- func Last[V any](seq iter.Seq[V]) (v V, ok bool)
- func Map[In, Out any](seq iter.Seq[In], f func(In) Out) iter.Seq[Out]
- func Map2[K, V, K2, V2 any](seq iter.Seq2[K, V], f func(K, V) (K2, V2)) iter.Seq2[K2, V2]
- func Max[V cmp.Ordered](seq iter.Seq[V]) (v V, ok bool)
- func MaxBy[V any](seq iter.Seq[V], cmpFn func(a, b V) int) (v V, ok bool)
- func Min[V cmp.Ordered](seq iter.Seq[V]) (v V, ok bool)
- func MinBy[V any](seq iter.Seq[V], cmpFn func(a, b V) int) (v V, ok bool)
- func None[V any](seq iter.Seq[V], f func(V) bool) bool
- func Nth[V any](seq iter.Seq[V], n int) (v V, ok bool)
- func Of[V any](vals ...V) iter.Seq[V]
- func Partition[V any](seq iter.Seq[V], f func(V) bool) (yes, no []V)
- func Peek[V any](seq iter.Seq[V], f func(V)) iter.Seq[V]
- func Range(start, stop int) iter.Seq[int]
- func RangeStep(start, stop, step int) iter.Seq[int]
- func Reduce[V, A any](seq iter.Seq[V], init A, f func(A, V) A) A
- func Repeat[V any](v V) iter.Seq[V]
- func RepeatN[V any](v V, n int) iter.Seq[V]
- func Sorted[V cmp.Ordered](seq iter.Seq[V]) iter.Seq[V]
- func SortedBy[V any](seq iter.Seq[V], cmpFn func(a, b V) int) iter.Seq[V]
- func StepBy[V any](seq iter.Seq[V], n int) iter.Seq[V]
- func Sum[V Number](seq iter.Seq[V]) V
- func Swap[K, V any](seq iter.Seq2[K, V]) iter.Seq2[V, K]
- func Take[V any](seq iter.Seq[V], n int) iter.Seq[V]
- func TakeWhile[V any](seq iter.Seq[V], f func(V) bool) iter.Seq[V]
- func Unique[V comparable](seq iter.Seq[V]) iter.Seq[V]
- func Values[K, V any](seq iter.Seq2[K, V]) iter.Seq[V]
- func Window[V any](seq iter.Seq[V], size int) iter.Seq[[]V]
- func Zip[A, B any](a iter.Seq[A], b iter.Seq[B]) iter.Seq2[A, B]
- type Chain
- func (c Chain[V]) All(f func(V) bool) bool
- func (c Chain[V]) Any(f func(V) bool) bool
- func (c Chain[V]) Collect() []V
- func (c Chain[V]) Concat(others ...iter.Seq[V]) Chain[V]
- func (c Chain[V]) Count() int
- func (c Chain[V]) Drop(n int) Chain[V]
- func (c Chain[V]) DropWhile(f func(V) bool) Chain[V]
- func (c Chain[V]) Filter(f func(V) bool) Chain[V]
- func (c Chain[V]) First() (V, bool)
- func (c Chain[V]) ForEach(f func(V))
- func (c Chain[V]) Last() (V, bool)
- func (c Chain[V]) None(f func(V) bool) bool
- func (c Chain[V]) Peek(f func(V)) Chain[V]
- func (c Chain[V]) Reduce(init V, f func(V, V) V) V
- func (c Chain[V]) Seq() iter.Seq[V]
- func (c Chain[V]) StepBy(n int) Chain[V]
- func (c Chain[V]) Take(n int) Chain[V]
- func (c Chain[V]) TakeWhile(f func(V) bool) Chain[V]
- type Number
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func All ¶
All returns true if f returns true for every element. Short-circuits on the first element for which f returns false.
func Any ¶
Any returns true if f returns true for at least one element. Short-circuits on the first match and does not consume the rest of seq.
func Chunk ¶
Chunk partitions seq into non-overlapping slices of length n. The last chunk may be smaller if the total element count is not a multiple of n. Panics if n < 1.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
for chunk := range iterx.Chunk(iterx.Of(1, 2, 3, 4, 5), 2) {
fmt.Println(chunk)
}
}
Output: [1 2] [3 4] [5]
func Collect ¶
Collect consumes seq and returns all elements as a slice. Returns nil for an empty sequence.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.Collect(iterx.Filter(iterx.Range(1, 10), func(n int) bool { return n%3 == 0 }))
fmt.Println(result)
}
Output: [3 6 9]
func CollectMap ¶
func CollectMap[K comparable, V any](seq iter.Seq2[K, V]) map[K]V
CollectMap drains a iter.Seq2 into a map. For duplicate keys, the last value encountered wins.
func Concat ¶
Concat returns a single iterator that yields all elements from each provided iterator in order.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.Collect(iterx.Concat(iterx.Of(1, 2), iterx.Of(3, 4), iterx.Of(5)))
fmt.Println(result)
}
Output: [1 2 3 4 5]
func Drop ¶
Drop skips the first n elements and returns the rest.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.Collect(iterx.Drop(iterx.Of(1, 2, 3, 4, 5), 2))
fmt.Println(result)
}
Output: [3 4 5]
func DropWhile ¶
DropWhile skips leading elements while f returns true, then yields all remaining elements.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.Collect(iterx.DropWhile(iterx.Of(1, 2, 3, 4, 5), func(n int) bool { return n < 3 }))
fmt.Println(result)
}
Output: [3 4 5]
func Enumerate ¶
Enumerate pairs each element with its zero-based index, returning a iter.Seq2.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
for i, v := range iterx.Enumerate(iterx.Of("x", "y", "z")) {
fmt.Printf("%d:%s\n", i, v)
}
}
Output: 0:x 1:y 2:z
func Filter ¶
Filter returns a new iterator containing only elements for which f returns true.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
even := iterx.Filter(iterx.Of(1, 2, 3, 4, 5), func(n int) bool { return n%2 == 0 })
fmt.Println(iterx.Collect(even))
}
Output: [2 4]
func First ¶
First returns the first element of seq, or the zero value and false if empty.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
v, ok := iterx.First(iterx.Filter(iterx.Range(1, 10), func(n int) bool { return n > 5 }))
fmt.Println(v, ok)
}
Output: 6 true
func FlatMap ¶
FlatMap applies f to each element and concatenates the resulting iterators.
Example ¶
package main
import (
"fmt"
"iter"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.FlatMap(iterx.Of(1, 2, 3), func(n int) iter.Seq[int] {
return iterx.RepeatN(n, n)
})
fmt.Println(iterx.Collect(result))
}
Output: [1 2 2 3 3 3]
func Generate ¶
Generate returns an infinite iterator whose first element is seed and each subsequent element is produced by calling next on the previous value. Callers must use Take, TakeWhile, or a manual break to avoid an infinite loop.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
powers := iterx.Collect(iterx.Take(iterx.Generate(1, func(n int) int { return n * 2 }), 5))
fmt.Println(powers)
}
Output: [1 2 4 8 16]
func GroupBy ¶
func GroupBy[K comparable, V any](seq iter.Seq[V], key func(V) K) map[K][]V
GroupBy collects elements into a map, grouping by the key returned by key(v).
Example ¶
package main
import (
"fmt"
"slices"
"github.com/renaldid/iterx"
)
func main() {
groups := iterx.GroupBy(iterx.Of(1, 2, 3, 4, 5, 6), func(n int) string {
if n%2 == 0 {
return "even"
}
return "odd"
})
slices.Sort(groups["even"])
slices.Sort(groups["odd"])
fmt.Println("even:", groups["even"])
fmt.Println("odd:", groups["odd"])
}
Output: even: [2 4 6] odd: [1 3 5]
func Keys ¶
Keys returns an iterator over the keys of seq.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
seq := iterx.Zip(iterx.Of("a", "b", "c"), iterx.Of(1, 2, 3))
keys := iterx.Collect(iterx.Keys(seq))
fmt.Println(keys)
}
Output: [a b c]
func Map ¶
Map transforms each element of seq using f and returns a new lazy iterator.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
doubled := iterx.Map(iterx.Of(1, 2, 3), func(n int) int { return n * 2 })
fmt.Println(iterx.Collect(doubled))
}
Output: [2 4 6]
func Max ¶
Max returns the largest element in seq using cmp.Compare. Returns the zero value and false for an empty sequence.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
v, _ := iterx.Max(iterx.Of(3, 1, 4, 1, 5, 9))
fmt.Println(v)
}
Output: 9
func MaxBy ¶
MaxBy returns the largest element according to cmpFn, which must follow the same sign convention as cmp.Compare (negative means a < b). Returns the zero value and false for an empty sequence.
func Min ¶
Min returns the smallest element in seq using cmp.Compare. Returns the zero value and false for an empty sequence.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
v, _ := iterx.Min(iterx.Of(3, 1, 4, 1, 5, 9))
fmt.Println(v)
}
Output: 1
func MinBy ¶
MinBy returns the smallest element according to cmpFn, which must follow the same sign convention as cmp.Compare (negative means a < b). Returns the zero value and false for an empty sequence.
func Nth ¶
Nth returns the n-th element (zero-based) of seq. Returns the zero value and false if seq has fewer than n+1 elements.
func Of ¶
Of returns an iterator over the provided values.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
for v := range iterx.Of(10, 20, 30) {
fmt.Println(v)
}
}
Output: 10 20 30
func Partition ¶
Partition splits seq into two slices: those for which f returns true (yes) and those for which it returns false (no).
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
yes, no := iterx.Partition(iterx.Of(1, 2, 3, 4, 5, 6), func(n int) bool { return n%2 == 0 })
fmt.Println("even:", yes)
fmt.Println("odd:", no)
}
Output: even: [2 4 6] odd: [1 3 5]
func Peek ¶
Peek returns an iterator that calls f on each element as a side effect, then passes the element through unchanged. Useful for logging or debugging.
func Range ¶
Range returns an iterator over the integers in [start, stop).
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.Collect(iterx.Range(1, 6))
fmt.Println(result)
}
Output: [1 2 3 4 5]
func RangeStep ¶
RangeStep returns an iterator starting at start, advancing by step, and stopping before stop. A positive step counts up; a negative step counts down. Panics if step is zero.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.Collect(iterx.RangeStep(0, 10, 2))
fmt.Println(result)
}
Output: [0 2 4 6 8]
func Reduce ¶
Reduce applies f cumulatively, left-to-right, starting from init: f(f(f(init, v0), v1), v2) … Returns init unchanged for an empty sequence.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
sum := iterx.Reduce(iterx.Of(1, 2, 3, 4, 5), 0, func(acc, v int) int { return acc + v })
fmt.Println(sum)
}
Output: 15
func Repeat ¶
Repeat returns an infinite iterator that always yields v. Callers must use Take, TakeWhile, or a manual break to avoid an infinite loop.
func RepeatN ¶
RepeatN returns an iterator that yields v exactly n times.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.Collect(iterx.RepeatN("go", 3))
fmt.Println(result)
}
Output: [go go go]
func Sorted ¶
Sorted collects seq into a slice, sorts it in ascending order using cmp.Compare, and returns an iterator over the sorted result.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.Collect(iterx.Sorted(iterx.Of(3, 1, 4, 1, 5, 9, 2, 6)))
fmt.Println(result)
}
Output: [1 1 2 3 4 5 6 9]
func SortedBy ¶
SortedBy collects seq into a slice, sorts it using cmpFn (same sign convention as cmp.Compare: negative means a < b), and returns an iterator over the result.
func StepBy ¶
StepBy returns every n-th element, starting from the first. Panics if n < 1.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.Collect(iterx.StepBy(iterx.Of(1, 2, 3, 4, 5, 6), 2))
fmt.Println(result)
}
Output: [1 3 5]
func Sum ¶
Sum returns the sum of all elements. Returns the zero value for an empty sequence.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
total := iterx.Sum(iterx.Of(1, 2, 3, 4, 5))
fmt.Println(total)
}
Output: 15
func Take ¶
Take returns at most the first n elements of seq.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
first3 := iterx.Collect(iterx.Take(iterx.Range(0, 100), 3))
fmt.Println(first3)
}
Output: [0 1 2]
func TakeWhile ¶
TakeWhile returns elements from seq as long as f returns true. It stops at the first element for which f returns false.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.Collect(iterx.TakeWhile(iterx.Of(1, 2, 3, 4, 5), func(n int) bool { return n < 4 }))
fmt.Println(result)
}
Output: [1 2 3]
func Unique ¶
func Unique[V comparable](seq iter.Seq[V]) iter.Seq[V]
Unique returns an iterator that skips duplicate elements. The first occurrence of each element is kept; later duplicates are dropped.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
result := iterx.Collect(iterx.Unique(iterx.Of(1, 2, 2, 3, 1, 4)))
fmt.Println(result)
}
Output: [1 2 3 4]
func Values ¶
Values returns an iterator over the values of seq.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
seq := iterx.Zip(iterx.Of("a", "b", "c"), iterx.Of(1, 2, 3))
vals := iterx.Collect(iterx.Values(seq))
fmt.Println(vals)
}
Output: [1 2 3]
func Window ¶
Window yields all contiguous sub-slices of length size using a sliding window. Panics if size < 1.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
for win := range iterx.Window(iterx.Of(1, 2, 3, 4, 5), 3) {
fmt.Println(win)
}
}
Output: [1 2 3] [2 3 4] [3 4 5]
func Zip ¶
Zip pairs elements from a and b into a iter.Seq2. Stops when the shorter sequence ends.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
keys := iterx.Of("a", "b", "c")
vals := iterx.Of(1, 2, 3)
for k, v := range iterx.Zip(keys, vals) {
fmt.Printf("%s=%d\n", k, v)
}
}
Output: a=1 b=2 c=3
Types ¶
type Chain ¶
type Chain[V any] struct { // contains filtered or unexported fields }
Chain wraps an iter.Seq to enable fluent method-chaining for adapters that preserve the element type.
For type-changing operations (Map, FlatMap, Enumerate, Zip, Chunk, Window) use the package-level free functions. Unwrap the underlying iterator with Chain.Seq and rewrap with From when mixing free functions into a chain:
names := iterx.From(
iterx.Map(
iterx.From(slices.Values(users)).Filter(isActive).Seq(),
func(u User) string { return u.Name },
),
)
Note: Chunk and Window are intentionally not methods on Chain because they change the element type to []V, which would create an instantiation cycle in the Go generics system. Use them as free functions:
iterx.From(iterx.Chunk(myChain.Seq(), 3))
func From ¶
From wraps seq in a Chain for fluent chaining.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
// Chain multiple adapters fluently
result := iterx.From(iterx.Range(1, 20)).
Filter(func(n int) bool { return n%2 == 0 }).
Drop(1).
Take(4).
Collect()
fmt.Println(result)
}
Output: [4 6 8 10]
func (Chain[V]) Collect ¶
func (c Chain[V]) Collect() []V
Collect consumes the sequence and returns all elements as a slice.
func (Chain[V]) DropWhile ¶
DropWhile skips leading elements while f returns true, then passes the rest through.
func (Chain[V]) Filter ¶
Filter returns a new Chain containing only elements for which f returns true.
func (Chain[V]) First ¶
First returns the first element, or the zero value and false for an empty sequence.
func (Chain[V]) Last ¶
Last returns the last element, or the zero value and false for an empty sequence.
func (Chain[V]) Reduce ¶
func (c Chain[V]) Reduce(init V, f func(V, V) V) V
Reduce applies f cumulatively starting from init. Both init and the accumulator are the same type V; for a different accumulator type use the package-level Reduce free function.
Example ¶
package main
import (
"fmt"
"github.com/renaldid/iterx"
)
func main() {
product := iterx.From(iterx.Of(1, 2, 3, 4, 5)).Reduce(1, func(a, v int) int { return a * v })
fmt.Println(product)
}
Output: 120
func (Chain[V]) Seq ¶
Seq returns the underlying iter.Seq. Use this to hand the iterator back to package-level free functions or stdlib range loops.