iterx

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: May 10, 2026 License: MIT Imports: 3 Imported by: 0

README

iterx

Go Reference Go Version Coverage

Composable, lazy iterator adapters for Go 1.23+.

iterx fills the gap left by the stdlib: Go 1.23 introduced iter.Seq[V] as the standard iterator type, but provides no way to compose them — you cannot write .Filter().Map().Take() and there is no official adapter library (the x/exp/xiter proposal has been open since 2023). iterx is that library.

result := iterx.From(slices.Values(products)).
    Filter(func(p Product) bool { return p.InStock }).
    Take(10).
    Collect()

Zero dependencies · 100% test coverage · Works with stdlib for range


Installation

go get github.com/renaldid/iterx

Requires Go 1.23 or later.


Quick examples

// Filter and collect
evens := iterx.Collect(iterx.Filter(iterx.Range(1, 11), func(n int) bool {
    return n%2 == 0
}))
// [2 4 6 8 10]

// Map changes the element type
names := iterx.Collect(iterx.Map(slices.Values(users), func(u User) string {
    return u.Name
}))

// Fluent chaining via Chain
top5 := iterx.From(slices.Values(scores)).
    Filter(func(s int) bool { return s >= 60 }).
    Drop(0).
    Take(5).
    Collect()

// Works with standard for range
for i, v := range iterx.Enumerate(slices.Values(items)) {
    fmt.Printf("[%d] %v\n", i, v)
}

// Sum / Min / Max
total := iterx.Sum(iterx.Map(slices.Values(orders), func(o Order) float64 {
    return o.Amount
}))

// Chunk into pages
for page := range iterx.Chunk(slices.Values(rows), 100) {
    insertBatch(page)
}

API

Transforms
Function Signature Description
Filter (Seq[V], func(V) bool) → Seq[V] Keep elements where f is true
Map (Seq[In], func(In) Out) → Seq[Out] Transform each element
FlatMap (Seq[In], func(In) Seq[Out]) → Seq[Out] Map then flatten
Flatten (Seq[Seq[V]]) → Seq[V] Merge nested iterators
Peek (Seq[V], func(V)) → Seq[V] Side-effect per element; passes through unchanged
Take (Seq[V], n) → Seq[V] First n elements
Drop (Seq[V], n) → Seq[V] Skip first n elements
TakeWhile (Seq[V], func(V) bool) → Seq[V] Take while predicate is true
DropWhile (Seq[V], func(V) bool) → Seq[V] Drop while predicate is true
StepBy (Seq[V], n) → Seq[V] Every n-th element (panics if n < 1)
Chunk (Seq[V], n) → Seq[[]V] Non-overlapping slices of n elements
Window (Seq[V], n) → Seq[[]V] Sliding windows of n elements
Concat (Seq[V]...) → Seq[V] Concatenate multiple iterators
Zip (Seq[A], Seq[B]) → Seq2[A, B] Pair elements; stops at shorter
Enumerate (Seq[V]) → Seq2[int, V] Pair with zero-based index
Unique (Seq[V]) → Seq[V] Remove duplicates (first occurrence kept)
Sorted (Seq[V]) → Seq[V] Collect, sort ascending, re-iterate
SortedBy (Seq[V], cmp) → Seq[V] Collect, sort with custom comparator
Sources
Function Description
Of(vals...) Iterator over literal values
Empty[V]() Iterator that yields nothing
Range(start, stop) Integers in [start, stop)
RangeStep(start, stop, step) Integers with custom step (panics if step == 0)
Repeat(v) Infinite repetition of v — use with Take
RepeatN(v, n) Repeat v exactly n times
Generate(seed, next) Infinite sequence — use with Take
Terminal operations
Function Description
Collect(seq) → []V
First(seq) → (V, bool) — first element
Last(seq) → (V, bool) — last element
Nth(seq, n) → (V, bool) — n-th element (0-based)
Count(seq) → int — number of elements
Any(seq, f) → bool — true if any element satisfies f (short-circuits)
All(seq, f) → bool — true if all elements satisfy f (short-circuits)
None(seq, f) → bool — true if no element satisfies f
ForEach(seq, f) Call f on every element
Reduce(seq, init, f) Left fold; accumulator type may differ from V
GroupBy(seq, key) → map[K][]V
Partition(seq, f) → (yes []V, no []V)
Numeric helpers
Function Constraint Description
Sum[V] Number Sum of all elements
Min[V] cmp.Ordered Smallest element
Max[V] cmp.Ordered Largest element
MinBy[V] any Smallest by custom comparator
MaxBy[V] any Largest by custom comparator

Number covers all built-in integer and float types (int, int8int64, uintuintptr, float32, float64) including custom types built on them.

Seq2 helpers

Functions that operate on iter.Seq2[K, V] (two-value iterators such as those produced by maps.All, Zip, or Enumerate):

Function Description
Keys(seq2) Iterator over keys
Values(seq2) Iterator over values
CollectMap(seq2) → map[K]V
Filter2(seq2, f) Keep pairs where f(k, v) is true
Map2(seq2, f) Transform each key-value pair
Swap(seq2) Exchange key and value positions
Chain — fluent chaining

From(seq) wraps any iter.Seq[V] in a Chain[V], making same-type adapters available as methods:

iterx.From(slices.Values(nums)).
    Filter(isPositive).
    Drop(5).
    Take(10).
    Collect()

Methods on Chain[V]: Filter, Take, Drop, TakeWhile, DropWhile, Peek, StepBy, Concat, Collect, First, Last, Count, Any, All, None, ForEach, Reduce, Seq.

Seq() unwraps the chain back to a plain iter.Seq[V], useful when handing off to a free function:

// Chain → free function → Chain again
iterx.From(
    iterx.Map(
        iterx.From(slices.Values(users)).Filter(isActive).Seq(),
        func(u User) string { return u.Name },
    ),
).Take(10).Collect()

Chunk and Window are not available as Chain methods because they change the element type to []V, which causes an instantiation cycle in Go's generics system. Use them as free functions:

iterx.From(iterx.Chunk(myChain.Seq(), 3))

Design notes

Lazy by default. Every adapter returns a new iter.Seq without reading the source. Work only happens when you range over or collect the result.

Zero allocation on the hot path. Filter, Map, Take, Drop, and similar adapters create only a closure; no slices are allocated until you call Collect. Chunk, Window, Sorted, and Unique allocate internally because they must buffer elements.

Fail fast on invalid arguments. Chunk, Window, StepBy, and RangeStep panic immediately (before returning the iterator) on invalid input (n < 1 or step == 0). This surfaces programmer errors at the call site rather than silently during iteration.

Compatible with stdlib for range. Every iter.Seq[V] returned by this package works directly in Go 1.23 range loops:

for v := range iterx.Filter(slices.Values(items), pred) {
    // ...
}

No global state. All functions are pure. Multiple goroutines may safely call any function concurrently as long as they hold separate iterators — each call creates independent closure state.


License

MIT

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

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func All

func All[V any](seq iter.Seq[V], f func(V) bool) bool

All returns true if f returns true for every element. Short-circuits on the first element for which f returns false.

func Any

func Any[V any](seq iter.Seq[V], f func(V) bool) bool

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

func Chunk[V any](seq iter.Seq[V], n int) iter.Seq[[]V]

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

func Collect[V any](seq iter.Seq[V]) []V

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

func Concat[V any](seqs ...iter.Seq[V]) iter.Seq[V]

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 Count

func Count[V any](seq iter.Seq[V]) int

Count consumes seq and returns the number of elements.

func Drop

func Drop[V any](seq iter.Seq[V], n int) iter.Seq[V]

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

func DropWhile[V any](seq iter.Seq[V], f func(V) bool) iter.Seq[V]

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 Empty

func Empty[V any]() iter.Seq[V]

Empty returns an iterator that yields no elements.

func Enumerate

func Enumerate[V any](seq iter.Seq[V]) iter.Seq2[int, V]

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

func Filter[V any](seq iter.Seq[V], f func(V) bool) iter.Seq[V]

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 Filter2

func Filter2[K, V any](seq iter.Seq2[K, V], f func(K, V) bool) iter.Seq2[K, V]

Filter2 returns a iter.Seq2 containing only pairs for which f returns true.

func First

func First[V any](seq iter.Seq[V]) (v V, ok bool)

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

func FlatMap[In, Out any](seq iter.Seq[In], f func(In) iter.Seq[Out]) iter.Seq[Out]

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 Flatten

func Flatten[V any](seq iter.Seq[iter.Seq[V]]) iter.Seq[V]

Flatten merges a sequence of iterators into a single sequential iterator.

func ForEach

func ForEach[V any](seq iter.Seq[V], f func(V))

ForEach calls f on each element of seq.

func Generate

func Generate[V any](seed V, next func(V) V) iter.Seq[V]

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

func Keys[K, V any](seq iter.Seq2[K, V]) iter.Seq[K]

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 Last

func Last[V any](seq iter.Seq[V]) (v V, ok bool)

Last returns the last element of seq, or the zero value and false if empty.

func Map

func Map[In, Out any](seq iter.Seq[In], f func(In) Out) iter.Seq[Out]

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 Map2

func Map2[K, V, K2, V2 any](seq iter.Seq2[K, V], f func(K, V) (K2, V2)) iter.Seq2[K2, V2]

Map2 transforms each key-value pair of seq using f.

func Max

func Max[V cmp.Ordered](seq iter.Seq[V]) (v V, ok bool)

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

func MaxBy[V any](seq iter.Seq[V], cmpFn func(a, b V) int) (v V, ok bool)

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

func Min[V cmp.Ordered](seq iter.Seq[V]) (v V, ok bool)

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

func MinBy[V any](seq iter.Seq[V], cmpFn func(a, b V) int) (v V, ok bool)

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 None

func None[V any](seq iter.Seq[V], f func(V) bool) bool

None returns true if f returns false for every element. Equivalent to !Any(seq, f).

func Nth

func Nth[V any](seq iter.Seq[V], n int) (v V, ok bool)

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

func Of[V any](vals ...V) iter.Seq[V]

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

func Partition[V any](seq iter.Seq[V], f func(V) bool) (yes, no []V)

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

func Peek[V any](seq iter.Seq[V], f func(V)) iter.Seq[V]

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

func Range(start, stop int) iter.Seq[int]

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

func RangeStep(start, stop, step int) iter.Seq[int]

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

func Reduce[V, A any](seq iter.Seq[V], init A, f func(A, V) A) A

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

func Repeat[V any](v V) iter.Seq[V]

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

func RepeatN[V any](v V, n int) iter.Seq[V]

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

func Sorted[V cmp.Ordered](seq iter.Seq[V]) iter.Seq[V]

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

func SortedBy[V any](seq iter.Seq[V], cmpFn func(a, b V) int) iter.Seq[V]

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

func StepBy[V any](seq iter.Seq[V], n int) iter.Seq[V]

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

func Sum[V Number](seq iter.Seq[V]) V

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 Swap

func Swap[K, V any](seq iter.Seq2[K, V]) iter.Seq2[V, K]

Swap returns a iter.Seq2 with the key and value positions exchanged.

func Take

func Take[V any](seq iter.Seq[V], n int) iter.Seq[V]

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

func TakeWhile[V any](seq iter.Seq[V], f func(V) bool) iter.Seq[V]

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

func Values[K, V any](seq iter.Seq2[K, V]) iter.Seq[V]

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

func Window[V any](seq iter.Seq[V], size int) iter.Seq[[]V]

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

func Zip[A, B any](a iter.Seq[A], b iter.Seq[B]) iter.Seq2[A, B]

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

func From[V any](seq iter.Seq[V]) Chain[V]

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]) All

func (c Chain[V]) All(f func(V) bool) bool

All returns true if f returns true for every element.

func (Chain[V]) Any

func (c Chain[V]) Any(f func(V) bool) bool

Any returns true if f returns true for at least one element.

func (Chain[V]) Collect

func (c Chain[V]) Collect() []V

Collect consumes the sequence and returns all elements as a slice.

func (Chain[V]) Concat

func (c Chain[V]) Concat(others ...iter.Seq[V]) Chain[V]

Concat appends the given iterators after the current sequence.

func (Chain[V]) Count

func (c Chain[V]) Count() int

Count consumes the sequence and returns the number of elements.

func (Chain[V]) Drop

func (c Chain[V]) Drop(n int) Chain[V]

Drop returns a new Chain with the first n elements removed.

func (Chain[V]) DropWhile

func (c Chain[V]) DropWhile(f func(V) bool) Chain[V]

DropWhile skips leading elements while f returns true, then passes the rest through.

func (Chain[V]) Filter

func (c Chain[V]) Filter(f func(V) bool) Chain[V]

Filter returns a new Chain containing only elements for which f returns true.

func (Chain[V]) First

func (c Chain[V]) First() (V, bool)

First returns the first element, or the zero value and false for an empty sequence.

func (Chain[V]) ForEach

func (c Chain[V]) ForEach(f func(V))

ForEach calls f on each element.

func (Chain[V]) Last

func (c Chain[V]) Last() (V, bool)

Last returns the last element, or the zero value and false for an empty sequence.

func (Chain[V]) None

func (c Chain[V]) None(f func(V) bool) bool

None returns true if f returns false for every element.

func (Chain[V]) Peek

func (c Chain[V]) Peek(f func(V)) Chain[V]

Peek calls f on each element as a side effect without consuming the element.

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

func (c Chain[V]) Seq() iter.Seq[V]

Seq returns the underlying iter.Seq. Use this to hand the iterator back to package-level free functions or stdlib range loops.

func (Chain[V]) StepBy

func (c Chain[V]) StepBy(n int) Chain[V]

StepBy returns every n-th element. Panics if n < 1.

func (Chain[V]) Take

func (c Chain[V]) Take(n int) Chain[V]

Take returns a new Chain with at most the first n elements.

func (Chain[V]) TakeWhile

func (c Chain[V]) TakeWhile(f func(V) bool) Chain[V]

TakeWhile returns elements while f returns true.

type Number

type Number interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 |
		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
		~float32 | ~float64
}

Number is a type constraint that permits all built-in integer and floating-point types.

Jump to

Keyboard shortcuts

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