Documentation
¶
Overview ¶
Package catena is a lazy, fully-typed sequence library for Go 1.27+, built on iter.Seq and generic methods.
The four types:
- Seq[T]: lazy, single-pass by contract, possibly infinite.
- Seq2[K, V]: the stdlib pairing currency; a bridge back to Seq, not a peer.
- Try[T]: Seq2[T, error]; error policy is chosen by the consumer (Collect stops at the first error, CollectAll drains, Ignore skips).
- List[T]: eager []T with the mirrored operation set.
Contracts every caller should know:
- Treat every Seq as single-pass. Re-iterability depends entirely on the producer (see the constructor table). Once() is a development guard.
- Nil sequences are empty: every method and package function accepts a nil receiver or argument and treats it as an empty sequence.
- Invalid construction arguments (negative counts, zero step) panic at construction time with a "catena: " prefixed message. Nil callbacks are not defended and panic at first use.
- Operators marked as buffering state their bound; terminals marked as full-drain hang on infinite input.
- Map-returning terminals return Go maps: iteration order is undefined.
- When a Try element carries a non-nil error, do not read the value.
- Not safe for concurrent use; ToChan is the fan-out mechanism.
- comparable-constrained functions panic at runtime if T is an interface type holding a non-comparable value (Go 1.20 semantics).
Example (LazyAcquisition) ¶
package main
import (
"bufio"
"fmt"
"strings"
"github.com/NerdMeNot/catena"
)
// Lines adapts an io.Reader into a Try of its lines — the §7.7 pattern.
// The reader is wrapped lazily inside the closure: a sequence that is
// never consumed never reads, and early termination stops the scan.
func Lines(open func() (*strings.Reader, error)) catena.Try[string] {
return func(yield func(string, error) bool) {
r, err := open()
if err != nil {
yield("", err)
return
}
sc := bufio.NewScanner(r)
for sc.Scan() {
if !yield(sc.Text(), nil) {
return
}
}
if err := sc.Err(); err != nil {
yield("", err)
}
}
}
func main() {
opened := 0
logs := Lines(func() (*strings.Reader, error) {
opened++
return strings.NewReader("GET /a\nPOST /b\nGET /c\nGET /d"), nil
})
// Building the pipeline opens nothing.
gets := logs.Ignore().
Filter(func(l string) bool { return strings.HasPrefix(l, "GET ") }).
Take(2)
fmt.Println("opened after building:", opened)
fmt.Println(gets.Collect())
fmt.Println("opened after consuming:", opened)
}
Output: opened after building: 0 [GET /a GET /c] opened after consuming: 1
Index ¶
- Constants
- func AssociateWith[T comparable, V any](s Seq[T], f func(T) V) map[T]V
- func Average[T Numeric](s Seq[T]) (float64, bool)
- func CollectMap[K comparable, V any](s Seq2[K, V]) map[K]V
- func Contains[T comparable](s Seq[T], v T) bool
- func Equal[T comparable](a, b Seq[T]) bool
- func IndexOf[T comparable](s Seq[T], v T) int
- func Join(s Seq[string], sep string) string
- func Max[T cmp.Ordered](s Seq[T]) (T, bool)
- func Min[T cmp.Ordered](s Seq[T]) (T, bool)
- func MinMax[T cmp.Ordered](s Seq[T]) (min, max T, ok bool)
- func Product[T Numeric](s Seq[T]) T
- func Self[T any](v T) T
- func Sum[T Numeric](s Seq[T]) T
- func Tally[T comparable](s Seq[T]) map[T]int
- func ToSet[T comparable](s Seq[T]) map[T]struct{}
- func TopN[T cmp.Ordered](s Seq[T], n int) []T
- func Unzip[K, V any](s Seq2[K, V]) ([]K, []V)
- type Integer
- type List
- func (l List[T]) All(pred func(T) bool) bool
- func (l List[T]) Any(pred func(T) bool) bool
- func (l List[T]) Append(vals ...T) List[T]
- func (l List[T]) AsSeq() Seq[T]
- func (l List[T]) Associate[K comparable, V any](f func(T) (K, V)) map[K]V
- func (l List[T]) At(i int) T
- func (l List[T]) AverageOf[N Numeric](sel func(T) N) (float64, bool)
- func (l List[T]) BottomNBy[K cmp.Ordered](n int, sel func(T) K) []T
- func (l List[T]) Clone() List[T]
- func (l List[T]) Collect() []T
- func (l List[T]) Concat(others ...Seq[T]) List[T]
- func (l List[T]) Count() int
- func (l List[T]) CountWhere(pred func(T) bool) int
- func (l List[T]) DedupeBy[K comparable](sel func(T) K) List[T]
- func (l List[T]) DistinctBy[K comparable](sel func(T) K) List[T]
- func (l List[T]) DistinctWith(eq func(a, b T) bool) List[T]
- func (l List[T]) Drain()
- func (l List[T]) Drop(n int) List[T]
- func (l List[T]) DropLast(n int) List[T]
- func (l List[T]) DropWhile(pred func(T) bool) List[T]
- func (l List[T]) ElementAt(i int) (T, bool)
- func (l List[T]) Filter(pred func(T) bool) List[T]
- func (l List[T]) FilterErr(pred func(T) (bool, error)) Try[T]
- func (l List[T]) FilterIndexed(pred func(int, T) bool) List[T]
- func (l List[T]) FilterMap[U any](f func(T) (U, bool)) List[U]
- func (l List[T]) FilterNot(pred func(T) bool) List[T]
- func (l List[T]) Find(pred func(T) bool) (T, bool)
- func (l List[T]) FindIndex(pred func(T) bool) int
- func (l List[T]) FindLast(pred func(T) bool) (T, bool)
- func (l List[T]) FindMap[U any](f func(T) (U, bool)) (U, bool)
- func (l List[T]) First() (T, bool)
- func (l List[T]) FlatMap[U any](f func(T) Seq[U]) List[U]
- func (l List[T]) FlatMapSlice[U any](f func(T) []U) List[U]
- func (l List[T]) Fold[A any](init A, f func(A, T) A) A
- func (l List[T]) FoldBy[K comparable, A any](key func(T) K, init func(K) A, f func(A, T) A) map[K]A
- func (l List[T]) FoldErr[A any](init A, f func(A, T) (A, error)) (A, error)
- func (l List[T]) FoldIndexed[A any](init A, f func(int, A, T) A) A
- func (l List[T]) FoldRight[A any](init A, f func(T, A) A) A
- func (l List[T]) FoldWhile[A any](init A, f func(A, T) (A, bool)) A
- func (l List[T]) ForEach(f func(T))
- func (l List[T]) ForEachErr(f func(T) error) error
- func (l List[T]) ForEachIndexed(f func(int, T))
- func (l List[T]) Get(i int) (T, bool)
- func (l List[T]) GroupBy[K comparable](sel func(T) K) map[K][]T
- func (l List[T]) IfEmpty(defaults ...T) List[T]
- func (l List[T]) IndexBy[K comparable](sel func(T) K) map[K]T
- func (l List[T]) Intersperse(sep T) List[T]
- func (l List[T]) IsEmpty() bool
- func (l List[T]) JoinBy[U any, K comparable, R any](other Seq[U], leftKey func(T) K, rightKey func(U) K, combine func(T, U) R) List[R]
- func (l List[T]) JoinToString(sep string, sel func(T) string) string
- func (l List[T]) Last() (T, bool)
- func (l List[T]) Len() int
- func (l List[T]) Map[U any](f func(T) U) List[U]
- func (l List[T]) MapErr[U any](f func(T) (U, error)) Try[U]
- func (l List[T]) MapIndexed[U any](f func(int, T) U) List[U]
- func (l List[T]) MaxBy[K cmp.Ordered](sel func(T) K) (T, bool)
- func (l List[T]) MaxOf[K cmp.Ordered](sel func(T) K) (K, bool)
- func (l List[T]) MaxWith(cmp func(a, b T) int) (T, bool)
- func (l List[T]) MinBy[K cmp.Ordered](sel func(T) K) (T, bool)
- func (l List[T]) MinMaxOf[K cmp.Ordered](sel func(T) K) (min, max K, ok bool)
- func (l List[T]) MinOf[K cmp.Ordered](sel func(T) K) (K, bool)
- func (l List[T]) MinWith(cmp func(a, b T) int) (T, bool)
- func (l List[T]) None(pred func(T) bool) bool
- func (l List[T]) OnEach(f func(T)) List[T]
- func (l List[T]) Partition(pred func(T) bool) (yes, no []T)
- func (l List[T]) Prepend(vals ...T) List[T]
- func (l List[T]) ProductOf[N Numeric](sel func(T) N) N
- func (l List[T]) Reduce(f func(T, T) T) (T, bool)
- func (l List[T]) Reversed() List[T]
- func (l List[T]) Scan[A any](init A, f func(A, T) A) List[A]
- func (l List[T]) Single() (T, bool)
- func (l List[T]) Slice(i, j int) List[T]
- func (l List[T]) SortedBy[K cmp.Ordered](sel func(T) K) List[T]
- func (l List[T]) SortedByDesc[K cmp.Ordered](sel func(T) K) List[T]
- func (l List[T]) SortedWith(cmp func(a, b T) int) List[T]
- func (l List[T]) Step(n int) List[T]
- func (l List[T]) SumOf[N Numeric](sel func(T) N) N
- func (l List[T]) Take(n int) List[T]
- func (l List[T]) TakeLast(n int) List[T]
- func (l List[T]) TakeWhile(pred func(T) bool) List[T]
- func (l List[T]) TallyBy[K comparable](sel func(T) K) map[K]int
- func (l List[T]) ToList() List[T]
- func (l List[T]) TopNBy[K cmp.Ordered](n int, sel func(T) K) []T
- func (l List[T]) WithIndex() Seq2[int, T]
- func (l List[T]) ZipWithNext() Seq2[T, T]
- type Numeric
- type Seq
- func Chain[T any](seqs ...Seq[T]) Seq[T]
- func Chunked[T any](s Seq[T], n int) Seq[[]T]
- func ChunkedBy[T any, K comparable](s Seq[T], sel func(T) K) Seq[[]T]
- func Cycle[T any](s Seq[T]) Seq[T]
- func Dedupe[T comparable](s Seq[T]) Seq[T]
- func Distinct[T comparable](s Seq[T]) Seq[T]
- func Empty[T any]() Seq[T]
- func Except[T comparable](a, b Seq[T]) Seq[T]
- func Flatten[T any](s Seq[Seq[T]]) Seq[T]
- func FlattenSlices[T any](s Seq[[]T]) Seq[T]
- func From[T any](seq func(func(T) bool)) Seq[T]
- func FromChan[T any](ctx context.Context, ch <-chan T) Seq[T]
- func FromSlice[T any](s []T) Seq[T]
- func Generate[T any](seed T, next func(T) T) Seq[T]
- func GenerateWhile[T any](seed T, next func(T) (T, bool)) Seq[T]
- func Intersect[T comparable](a, b Seq[T]) Seq[T]
- func NonZero[T comparable](s Seq[T]) Seq[T]
- func Of[T any](vals ...T) Seq[T]
- func Once1[T any](v T) Seq[T]
- func Range[I Integer](start, stop, step I) Seq[I]
- func Repeat[T any](v T) Seq[T]
- func RepeatN[T any](v T, n int) Seq[T]
- func Sorted[T cmp.Ordered](s Seq[T]) Seq[T]
- func SortedDesc[T cmp.Ordered](s Seq[T]) Seq[T]
- func Union[T comparable](a, b Seq[T]) Seq[T]
- func Windowed[T any](s Seq[T], size, step int) Seq[[]T]
- func (s Seq[T]) All(pred func(T) bool) bool
- func (s Seq[T]) Any(pred func(T) bool) bool
- func (s Seq[T]) Append(vals ...T) Seq[T]
- func (s Seq[T]) Associate[K comparable, V any](f func(T) (K, V)) map[K]V
- func (s Seq[T]) AverageOf[N Numeric](sel func(T) N) (float64, bool)
- func (s Seq[T]) BottomNBy[K cmp.Ordered](n int, sel func(T) K) []T
- func (s Seq[T]) Collect() []T
- func (s Seq[T]) Concat(others ...Seq[T]) Seq[T]
- func (s Seq[T]) Count() int
- func (s Seq[T]) CountWhere(pred func(T) bool) int
- func (s Seq[T]) DedupeBy[K comparable](sel func(T) K) Seq[T]
- func (s Seq[T]) DistinctBy[K comparable](sel func(T) K) Seq[T]
- func (s Seq[T]) DistinctWith(eq func(a, b T) bool) Seq[T]
- func (s Seq[T]) Drain()
- func (s Seq[T]) Drop(n int) Seq[T]
- func (s Seq[T]) DropLast(n int) Seq[T]
- func (s Seq[T]) DropWhile(pred func(T) bool) Seq[T]
- func (s Seq[T]) ElementAt(i int) (T, bool)
- func (s Seq[T]) Filter(pred func(T) bool) Seq[T]
- func (s Seq[T]) FilterErr(pred func(T) (bool, error)) Try[T]
- func (s Seq[T]) FilterIndexed(pred func(int, T) bool) Seq[T]
- func (s Seq[T]) FilterMap[U any](f func(T) (U, bool)) Seq[U]
- func (s Seq[T]) FilterNot(pred func(T) bool) Seq[T]
- func (s Seq[T]) Find(pred func(T) bool) (T, bool)
- func (s Seq[T]) FindIndex(pred func(T) bool) int
- func (s Seq[T]) FindLast(pred func(T) bool) (T, bool)
- func (s Seq[T]) FindMap[U any](f func(T) (U, bool)) (U, bool)
- func (s Seq[T]) First() (T, bool)
- func (s Seq[T]) FlatMap[U any](f func(T) Seq[U]) Seq[U]
- func (s Seq[T]) FlatMapSlice[U any](f func(T) []U) Seq[U]
- func (s Seq[T]) Fold[A any](init A, f func(A, T) A) A
- func (s Seq[T]) FoldBy[K comparable, A any](key func(T) K, init func(K) A, f func(A, T) A) map[K]A
- func (s Seq[T]) FoldErr[A any](init A, f func(A, T) (A, error)) (A, error)
- func (s Seq[T]) FoldIndexed[A any](init A, f func(int, A, T) A) A
- func (s Seq[T]) FoldWhile[A any](init A, f func(A, T) (A, bool)) A
- func (s Seq[T]) ForEach(f func(T))
- func (s Seq[T]) ForEachErr(f func(T) error) error
- func (s Seq[T]) ForEachIndexed(f func(int, T))
- func (s Seq[T]) GroupBy[K comparable](sel func(T) K) map[K][]T
- func (s Seq[T]) IfEmpty(defaults ...T) Seq[T]
- func (s Seq[T]) IndexBy[K comparable](sel func(T) K) map[K]T
- func (s Seq[T]) Intersperse(sep T) Seq[T]
- func (s Seq[T]) IsEmpty() bool
- func (s Seq[T]) JoinBy[U any, K comparable, R any](other Seq[U], leftKey func(T) K, rightKey func(U) K, combine func(T, U) R) Seq[R]
- func (s Seq[T]) JoinToString(sep string, sel func(T) string) string
- func (s Seq[T]) Last() (T, bool)
- func (s Seq[T]) Map[U any](f func(T) U) Seq[U]
- func (s Seq[T]) MapErr[U any](f func(T) (U, error)) Try[U]
- func (s Seq[T]) MapIndexed[U any](f func(int, T) U) Seq[U]
- func (s Seq[T]) MaxBy[K cmp.Ordered](sel func(T) K) (T, bool)
- func (s Seq[T]) MaxOf[K cmp.Ordered](sel func(T) K) (K, bool)
- func (s Seq[T]) MaxWith(cmp func(a, b T) int) (T, bool)
- func (s Seq[T]) MinBy[K cmp.Ordered](sel func(T) K) (T, bool)
- func (s Seq[T]) MinMaxOf[K cmp.Ordered](sel func(T) K) (min, max K, ok bool)
- func (s Seq[T]) MinOf[K cmp.Ordered](sel func(T) K) (K, bool)
- func (s Seq[T]) MinWith(cmp func(a, b T) int) (T, bool)
- func (s Seq[T]) None(pred func(T) bool) bool
- func (s Seq[T]) OnEach(f func(T)) Seq[T]
- func (s Seq[T]) Once() Seq[T]
- func (s Seq[T]) Partition(pred func(T) bool) (yes, no []T)
- func (s Seq[T]) Prepend(vals ...T) Seq[T]
- func (s Seq[T]) ProductOf[N Numeric](sel func(T) N) N
- func (s Seq[T]) Pull() (next func() (T, bool), stop func())
- func (s Seq[T]) Reduce(f func(T, T) T) (T, bool)
- func (s Seq[T]) Reversed() Seq[T]
- func (s Seq[T]) Scan[A any](init A, f func(A, T) A) Seq[A]
- func (s Seq[T]) Seq() iter.Seq[T]
- func (s Seq[T]) Single() (T, bool)
- func (s Seq[T]) SortedBy[K cmp.Ordered](sel func(T) K) Seq[T]
- func (s Seq[T]) SortedByDesc[K cmp.Ordered](sel func(T) K) Seq[T]
- func (s Seq[T]) SortedWith(cmp func(a, b T) int) Seq[T]
- func (s Seq[T]) Step(n int) Seq[T]
- func (s Seq[T]) SumOf[N Numeric](sel func(T) N) N
- func (s Seq[T]) Take(n int) Seq[T]
- func (s Seq[T]) TakeLast(n int) Seq[T]
- func (s Seq[T]) TakeWhile(pred func(T) bool) Seq[T]
- func (s Seq[T]) TallyBy[K comparable](sel func(T) K) map[K]int
- func (s Seq[T]) ToChan(ctx context.Context) <-chan T
- func (s Seq[T]) ToList() List[T]
- func (s Seq[T]) TopNBy[K cmp.Ordered](n int, sel func(T) K) []T
- func (s Seq[T]) UntilDone(ctx context.Context) Try[T]
- func (s Seq[T]) WithIndex() Seq2[int, T]
- func (s Seq[T]) Zip[U any](other Seq[U]) Seq2[T, U]
- func (s Seq[T]) ZipWithNext() Seq2[T, T]
- type Seq2
- func (s Seq2[K, V]) All(pred func(K, V) bool) bool
- func (s Seq2[K, V]) Any(pred func(K, V) bool) bool
- func (s Seq2[K, V]) Count() int
- func (s Seq2[K, V]) Drop(n int) Seq2[K, V]
- func (s Seq2[K, V]) Filter(pred func(K, V) bool) Seq2[K, V]
- func (s Seq2[K, V]) FilterNot(pred func(K, V) bool) Seq2[K, V]
- func (s Seq2[K, V]) First() (K, V, bool)
- func (s Seq2[K, V]) Fold[A any](init A, f func(A, K, V) A) A
- func (s Seq2[K, V]) ForEach(f func(K, V))
- func (s Seq2[K, V]) Keys() Seq[K]
- func (s Seq2[K, V]) Map[K2, V2 any](f func(K, V) (K2, V2)) Seq2[K2, V2]
- func (s Seq2[K, V]) MapTo[U any](f func(K, V) U) Seq[U]
- func (s Seq2[K, V]) MapValues[V2 any](f func(K, V) V2) Seq2[K, V2]
- func (s Seq2[K, V]) Pull() (next func() (K, V, bool), stop func())
- func (s Seq2[K, V]) Seq2() iter.Seq2[K, V]
- func (s Seq2[K, V]) Swap() Seq2[V, K]
- func (s Seq2[K, V]) Take(n int) Seq2[K, V]
- func (s Seq2[K, V]) Values() Seq[V]
- type Try
- func (t Try[T]) Collect() ([]T, error)
- func (t Try[T]) CollectAll() ([]T, []error)
- func (t Try[T]) Count() (int, error)
- func (t Try[T]) Drop(n int) Try[T]
- func (t Try[T]) Err() error
- func (t Try[T]) Errs() Seq[error]
- func (t Try[T]) Filter(pred func(T) bool) Try[T]
- func (t Try[T]) FilterErr(pred func(T) (bool, error)) Try[T]
- func (t Try[T]) FlatMap[U any](f func(T) Try[U]) Try[U]
- func (t Try[T]) Fold[A any](init A, f func(A, T) A) (A, error)
- func (t Try[T]) ForEach(f func(T) error) error
- func (t Try[T]) Ignore() Seq[T]
- func (t Try[T]) Map[U any](f func(T) U) Try[U]
- func (t Try[T]) MapErr[U any](f func(T) (U, error)) Try[U]
- func (t Try[T]) Must() Seq[T]
- func (t Try[T]) OnEach(f func(T)) Try[T]
- func (t Try[T]) OnError(f func(error)) Try[T]
- func (t Try[T]) Pull() (next func() (T, error, bool), stop func())
- func (t Try[T]) Recover(f func(error) (T, bool)) Try[T]
- func (t Try[T]) Seq2() iter.Seq2[T, error]
- func (t Try[T]) Take(n int) Try[T]
- func (t Try[T]) TakeWhile(pred func(T) bool) Try[T]
- func (t Try[T]) UntilDone(ctx context.Context) Try[T]
- func (t Try[T]) WrapErr(f func(error) error) Try[T]
Examples ¶
Constants ¶
const Version = "1.0.0"
Version is the library's version, kept in lockstep with release tags: the release workflow refuses to publish a tag that disagrees with it.
Variables ¶
This section is empty.
Functions ¶
func AssociateWith ¶
func AssociateWith[T comparable, V any](s Seq[T], f func(T) V) map[T]V
AssociateWith maps each element to f(element); on duplicate elements the last value wins. ⚠ Full drain; map iteration order is undefined.
func Average ¶
Average returns the mean, accumulating in float64; (0, false) on empty input. ⚠ Full drain.
func CollectMap ¶
func CollectMap[K comparable, V any](s Seq2[K, V]) map[K]V
CollectMap drains a pair sequence into a map; on duplicate keys the last value wins. ⚠ Full drain; map iteration order is undefined.
func Contains ¶
func Contains[T comparable](s Seq[T], v T) bool
Contains reports whether v occurs in s; stops at the first match.
func Equal ¶
func Equal[T comparable](a, b Seq[T]) bool
Equal reports whether a and b yield the same elements in the same order. Consumes both sequences up to and including the first difference — fully when they are equal. b is consumed through iter.Pull (its cleanup always runs).
func IndexOf ¶
func IndexOf[T comparable](s Seq[T], v T) int
IndexOf returns the index of the first occurrence of v; -1 if none.
func Max ¶
Max returns the largest element; NaN orders below everything (cmp.Compare). ⚠ Full drain.
func Min ¶
Min returns the smallest element; NaN orders below everything, so a NaN in the input is the minimum. ⚠ Full drain.
func Product ¶
Product multiplies the elements. Empty input yields 1, the multiplicative identity. ⚠ Full drain.
func Self ¶
func Self[T any](v T) T
Self is the identity selector: catena.Flatten(s) is s.FlatMap(Self).
func Sum ¶
Sum adds the elements; integer overflow wraps like +. Empty input sums to 0. ⚠ Full drain.
func Tally ¶
func Tally[T comparable](s Seq[T]) map[T]int
Tally counts occurrences per value. ⚠ Full drain; map iteration order is undefined.
func ToSet ¶
func ToSet[T comparable](s Seq[T]) map[T]struct{}
ToSet drains the sequence into a set. ⚠ Full drain; map iteration order is undefined.
Types ¶
type Integer ¶
type Integer interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}
Integer is the constraint for Range.
type List ¶
type List[T any] []T
List is an eager []T with the mirrored operation set. []T(l) unwraps it with no copy.
func (List[T]) Append ¶
Append returns a new List with vals appended. Unlike the built-in append, the result ALWAYS has a fresh backing array and never aliases l — consistent with every other List transform. Callers who want the built-in's amortized behavior can use it directly: List is a []T.
func (List[T]) AsSeq ¶
AsSeq returns a lazy, re-iterable view of the list. The list is not copied; mutations are visible to later iterations.
func (List[T]) Associate ¶
func (l List[T]) Associate[K comparable, V any](f func(T) (K, V)) map[K]V
Associate mirrors Seq.Associate eagerly.
func (List[T]) At ¶
At returns the element at index i, panicking exactly like l[i] on an out-of-range index. O(1).
func (List[T]) Collect ¶
func (l List[T]) Collect() []T
Collect mirrors Seq.Collect eagerly. O(1)/exact-allocation override.
func (List[T]) CountWhere ¶
CountWhere mirrors Seq.CountWhere eagerly.
func (List[T]) DedupeBy ¶
func (l List[T]) DedupeBy[K comparable](sel func(T) K) List[T]
DedupeBy mirrors Seq.DedupeBy eagerly.
func (List[T]) DistinctBy ¶
func (l List[T]) DistinctBy[K comparable](sel func(T) K) List[T]
DistinctBy mirrors Seq.DistinctBy eagerly.
func (List[T]) DistinctWith ¶
DistinctWith mirrors Seq.DistinctWith eagerly.
func (List[T]) FilterIndexed ¶
FilterIndexed mirrors Seq.FilterIndexed eagerly.
func (List[T]) FlatMapSlice ¶
FlatMapSlice mirrors Seq.FlatMapSlice eagerly.
func (List[T]) FoldBy ¶
func (l List[T]) FoldBy[K comparable, A any](key func(T) K, init func(K) A, f func(A, T) A) map[K]A
FoldBy mirrors Seq.FoldBy eagerly.
func (List[T]) FoldIndexed ¶
FoldIndexed mirrors Seq.FoldIndexed eagerly.
func (List[T]) FoldRight ¶
FoldRight reduces right to left. It exists only on List: a right fold needs the whole sequence in memory, which a List already is (§7.5).
func (List[T]) ForEachErr ¶
ForEachErr mirrors Seq.ForEachErr eagerly.
func (List[T]) ForEachIndexed ¶
ForEachIndexed mirrors Seq.ForEachIndexed eagerly.
func (List[T]) Get ¶
Get returns the element at index i; (zero, false) for a negative or out-of-range index. O(1).
func (List[T]) GroupBy ¶
func (l List[T]) GroupBy[K comparable](sel func(T) K) map[K][]T
GroupBy mirrors Seq.GroupBy eagerly.
func (List[T]) IndexBy ¶
func (l List[T]) IndexBy[K comparable](sel func(T) K) map[K]T
IndexBy mirrors Seq.IndexBy eagerly.
func (List[T]) Intersperse ¶
Intersperse mirrors Seq.Intersperse eagerly.
func (List[T]) JoinBy ¶
func (l List[T]) JoinBy[U any, K comparable, R any](other Seq[U], leftKey func(T) K, rightKey func(U) K, combine func(T, U) R) List[R]
JoinBy mirrors Seq.JoinBy eagerly.
func (List[T]) JoinToString ¶
JoinToString mirrors Seq.JoinToString eagerly.
func (List[T]) MapIndexed ¶
MapIndexed mirrors Seq.MapIndexed eagerly. O(1)/exact-allocation override.
func (List[T]) Slice ¶
Slice returns l[i:j] as a List, panicking exactly like the slice expression — and, exactly like it, sharing the backing array.
func (List[T]) SortedByDesc ¶
SortedByDesc mirrors Seq.SortedByDesc eagerly.
func (List[T]) SortedWith ¶
SortedWith mirrors Seq.SortedWith eagerly.
func (List[T]) TallyBy ¶
func (l List[T]) TallyBy[K comparable](sel func(T) K) map[K]int
TallyBy mirrors Seq.TallyBy eagerly.
func (List[T]) ZipWithNext ¶
ZipWithNext mirrors Seq.ZipWithNext eagerly.
type Numeric ¶
type Numeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64
}
Numeric is the constraint for arithmetic aggregations (Sum, Product, Average). Complex types are deliberately excluded: they are unordered and half the aggregation surface would be meaningless for them.
type Seq ¶
Seq is a lazy sequence: iter.Seq with methods. Range over it directly.
func Chunked ¶
Chunked yields consecutive chunks of n elements; the last chunk may be partial. Every chunk is a fresh slice (safe to retain). Panics if n <= 0.
Chunked is a package function, not a method: a method on Seq[T] returning Seq[[]T] is an instantiation cycle (each Seq[T] would require Seq[[]T], which would require Seq[[][]T], forever).
func ChunkedBy ¶
func ChunkedBy[T any, K comparable](s Seq[T], sel func(T) K) Seq[[]T]
ChunkedBy yields runs of consecutive elements sharing a key: a chunk closes when the key changes. Memory is bounded by the longest run. Every chunk is a fresh slice. A package function for the same instantiation- cycle reason as Chunked.
func Cycle ¶
Cycle yields s over and over, forever. The first pass is buffered and replayed (⚠ unbounded memory in len(s)). An empty s yields an empty Cycle — it terminates rather than spinning.
func Dedupe ¶
func Dedupe[T comparable](s Seq[T]) Seq[T]
Dedupe yields elements that differ from their predecessor — consecutive duplicates only, O(1) memory.
func Distinct ¶
func Distinct[T comparable](s Seq[T]) Seq[T]
Distinct yields elements not seen before; the first occurrence wins. ⚠ Retains one entry per distinct value — unbounded.
func Except ¶
func Except[T comparable](a, b Seq[T]) Seq[T]
Except yields the distinct elements of a that do not occur in b, in a's encounter order. ⚠ Buffers all of b before a is consumed, plus a seen- set of a's distinct values.
func FlattenSlices ¶
FlattenSlices yields every element of every slice, in order.
func From ¶
From adapts any push-function sequence — iter.Seq, catena.Seq, or a third-party alias — with no conversion at the call site. Re-iterability depends on the source.
func FromChan ¶
FromChan yields values received from ch until ch is closed or ctx is done. Single-use. No goroutine is started; a sequence that is never consumed never receives.
func FromSlice ¶
FromSlice returns a re-iterable Seq over s. The slice is not copied; mutations to it are visible to later iterations.
func Generate ¶
Generate yields seed, then next(seed), then next(next(seed)), forever. Infinite. Re-iterable iff next is pure.
func GenerateWhile ¶
GenerateWhile yields seed unconditionally, then successive next values until next reports false.
func Intersect ¶
func Intersect[T comparable](a, b Seq[T]) Seq[T]
Intersect yields the distinct elements of a that occur in b, in a's encounter order. ⚠ Buffers all of b before a is consumed, plus a seen- set of a's distinct values.
func NonZero ¶
func NonZero[T comparable](s Seq[T]) Seq[T]
NonZero yields the elements that are not the zero value of T.
func Once1 ¶
Once1 returns a re-iterable Seq of exactly one value. (Once, without the suffix, is the single-use guard method on Seq.)
func Range ¶
Range yields start, start+step, ... while the value is before stop (exclusive). step == 0 panics at construction; a sign mismatch between step and the start→stop direction yields an empty sequence. Termination is overflow-guarded: a step past the type's edge stops rather than wrapping. Unsigned types cannot step downward.
Example ¶
package main
import (
"fmt"
"github.com/NerdMeNot/catena"
)
func main() {
evens := catena.Range(0, 10, 2).
Map(func(n int) int { return n * n }).
Collect()
fmt.Println(evens)
}
Output: [0 4 16 36 64]
func Sorted ¶
Sorted yields the elements in ascending order, stably. NaN sorts first. ⚠ Buffers the entire input.
func SortedDesc ¶
SortedDesc yields the elements in descending order, stably. ⚠ Buffers the entire input.
func Union ¶
func Union[T comparable](a, b Seq[T]) Seq[T]
Union yields the distinct elements of a, then the distinct elements of b not in a — set semantics, encounter order. ⚠ Retains one entry per distinct value — unbounded.
func Windowed ¶
Windowed yields sliding windows of exactly size elements, advancing by step; trailing elements that do not fill a window are dropped. step > size is valid and samples with gaps. ⚠ Buffers size elements. Every window is a fresh slice. Panics if size or step is <= 0. A package function for the same instantiation-cycle reason as Chunked.
func (Seq[T]) All ¶
All reports whether pred admits every element; stops at the first counterexample. Vacuously true on empty input.
func (Seq[T]) Associate ¶
func (s Seq[T]) Associate[K comparable, V any](f func(T) (K, V)) map[K]V
Associate builds a map from f's key/value pairs; on duplicate keys the last pair wins. ⚠ Full drain; map iteration order is undefined.
func (Seq[T]) AverageOf ¶
AverageOf returns the mean of the selected values, accumulating in float64 (naive summation — precision for large integer inputs is not guaranteed); (0, false) on empty input. ⚠ Full drain.
func (Seq[T]) BottomNBy ¶
BottomNBy returns the n elements with the smallest keys, sorted ascending by key; equal keys retain encounter order. Memory is O(n). ⚠ Full drain. Panics if n is negative.
func (Seq[T]) Collect ¶
func (s Seq[T]) Collect() []T
Collect drains the sequence into a slice; nil for empty. ⚠ Full drain.
func (Seq[T]) CountWhere ¶
CountWhere returns the number of elements pred admits. ⚠ Full drain.
func (Seq[T]) DedupeBy ¶
func (s Seq[T]) DedupeBy[K comparable](sel func(T) K) Seq[T]
DedupeBy yields elements whose key differs from the previous element's key — consecutive duplicates only, O(1) memory. On key-sorted input it equals DistinctBy at a fraction of the cost.
func (Seq[T]) DistinctBy ¶
func (s Seq[T]) DistinctBy[K comparable](sel func(T) K) Seq[T]
DistinctBy yields elements whose key has not been seen before; the first occurrence wins. ⚠ Retains one key per distinct value — unbounded.
func (Seq[T]) DistinctWith ¶
DistinctWith yields elements no earlier element equals under eq. First occurrence wins. ⚠ Retains all distinct elements and compares in O(n²) — small inputs only.
func (Seq[T]) Drain ¶
func (s Seq[T]) Drain()
Drain consumes the sequence for its side effects. ⚠ Full drain.
func (Seq[T]) DropLast ¶
DropLast yields all but the final n elements, emitting with an n-element lag (⚠ buffers n). Panics if n is negative.
func (Seq[T]) DropWhile ¶
DropWhile skips elements until pred first returns false, then yields the rest.
func (Seq[T]) ElementAt ¶
ElementAt returns the element at index i; (zero, false) for a negative or out-of-range index.
func (Seq[T]) FilterErr ¶
FilterErr yields elements pred admits, as a Try; a failed pred call yields (zero, err).
func (Seq[T]) FilterIndexed ¶
FilterIndexed yields the elements for which pred(index, element) returns true. The index counts source elements from 0.
func (Seq[T]) FilterMap ¶
FilterMap yields the mapped value for each element f reports true for — a fused Map + Filter.
func (Seq[T]) FindMap ¶
FindMap returns the first mapped value f reports true for — a fused Find + Map.
func (Seq[T]) FlatMapSlice ¶
FlatMapSlice yields all elements of the slice f(v) for each element v.
func (Seq[T]) FoldBy ¶
func (s Seq[T]) FoldBy[K comparable, A any]( key func(T) K, init func(K) A, f func(A, T) A, ) map[K]A
FoldBy folds each element into a per-key accumulator: streaming grouped aggregation with no intermediate per-key slices. init is called once per distinct key. Memory is bounded by the number of distinct keys, not elements. ⚠ Full drain; map iteration order is undefined.
Example ¶
package main
import (
"fmt"
"github.com/NerdMeNot/catena"
)
func main() {
type order struct {
user string
amount int
}
orders := catena.Of(
order{"ada", 30}, order{"bob", 10}, order{"ada", 25}, order{"bob", 5},
)
// Streaming per-key aggregation: no intermediate map[string][]order.
totals := orders.FoldBy(
func(o order) string { return o.user },
func(string) int { return 0 },
func(sum int, o order) int { return sum + o.amount },
)
fmt.Println(totals["ada"], totals["bob"])
}
Output: 55 15
func (Seq[T]) FoldErr ¶
FoldErr folds until f fails, returning the accumulator so far and the first error.
func (Seq[T]) FoldIndexed ¶
FoldIndexed is Fold with the element index. ⚠ Full drain.
func (Seq[T]) FoldWhile ¶
FoldWhile folds until f reports false; the accumulator from the stopping call is included in the result.
func (Seq[T]) ForEach ¶
func (s Seq[T]) ForEach(f func(T))
ForEach calls f on every element. ⚠ Full drain.
func (Seq[T]) ForEachErr ¶
ForEachErr calls f on every element, stopping at and returning the first non-nil error; nil if the sequence drains clean.
func (Seq[T]) ForEachIndexed ¶
ForEachIndexed calls f(index, element) on every element. ⚠ Full drain.
func (Seq[T]) GroupBy ¶
func (s Seq[T]) GroupBy[K comparable](sel func(T) K) map[K][]T
GroupBy collects elements into per-key buckets, each in encounter order. ⚠ Full drain; retains every element; map iteration order is undefined.
func (Seq[T]) IndexBy ¶
func (s Seq[T]) IndexBy[K comparable](sel func(T) K) map[K]T
IndexBy maps each key to its element; on duplicate keys the last element wins. ⚠ Full drain; map iteration order is undefined.
func (Seq[T]) Intersperse ¶
Intersperse yields sep between consecutive elements.
func (Seq[T]) IsEmpty ¶
IsEmpty reports whether the sequence yields nothing. ⚠ It does so by consuming one element — on a single-pass source that element is lost.
func (Seq[T]) JoinBy ¶
func (s Seq[T]) JoinBy[U any, K comparable, R any]( other Seq[U], leftKey func(T) K, rightKey func(U) K, combine func(T, U) R, ) Seq[R]
JoinBy is a relational inner join: it pairs each element of s with every element of other sharing the same key and yields combine for each pair. Unmatched elements on either side are dropped; duplicate keys produce the cross product per key. Output order is left encounter order, then right encounter order within a key. ⚠ Buffers all of other before the first emission.
func (Seq[T]) JoinToString ¶
JoinToString concatenates the selected strings with sep between elements. ⚠ Full drain.
func (Seq[T]) MapErr ¶
MapErr yields f applied to each element as a Try; a failed call yields (zero, err).
func (Seq[T]) MapIndexed ¶
MapIndexed yields f(index, element), counting from 0.
func (Seq[T]) MaxBy ¶
MaxBy returns the element with the largest key; the earliest maximal element wins ties. NaN keys order below everything (cmp.Compare). ⚠ Full drain.
func (Seq[T]) MaxWith ¶
MaxWith returns the largest element under cmp; the earliest maximal element wins ties. ⚠ Full drain.
func (Seq[T]) MinBy ¶
MinBy returns the element with the smallest key; the earliest minimal element wins ties. ⚠ Full drain.
func (Seq[T]) MinWith ¶
MinWith returns the smallest element under cmp; the earliest minimal element wins ties. ⚠ Full drain.
func (Seq[T]) Once ¶
Once returns a sequence that panics if iterated more than once — a development guard for the single-pass contract, not a synchronization mechanism. This is the one operator whose state deliberately lives outside the iteration closure.
func (Seq[T]) Partition ¶
Partition splits elements by pred, preserving encounter order on both sides; nil slices for empty sides. ⚠ Full drain.
func (Seq[T]) ProductOf ¶
ProductOf multiplies the selected values. Empty input yields 1, the multiplicative identity. ⚠ Full drain.
func (Seq[T]) Pull ¶
Pull converts s to a pull-based iterator. THE CALLER MUST CALL stop, even if next has returned false, or resources held by s will leak.
func (Seq[T]) Reduce ¶
Reduce folds the sequence using its first element as the initial accumulator; (zero, false) on empty input. ⚠ Full drain.
func (Seq[T]) Reversed ¶
Reversed yields the elements in reverse order. ⚠ Buffers the entire input — hangs on infinite input.
func (Seq[T]) Scan ¶
Scan yields the running accumulator: f(init, e0), f(that, e1), ... The initial value itself is not yielded.
func (Seq[T]) Single ¶
Single returns the element iff the sequence has exactly one; it stops consuming upon seeing a second.
func (Seq[T]) SortedBy ¶
SortedBy yields the elements sorted ascending by key, stably. sel is called exactly once per element (decorate-sort-undecorate). ⚠ Buffers the entire input — hangs on infinite input.
func (Seq[T]) SortedByDesc ¶
SortedByDesc yields the elements sorted descending by key, stably. sel is called exactly once per element. ⚠ Buffers the entire input — hangs on infinite input.
func (Seq[T]) SortedWith ¶
SortedWith yields the elements sorted by cmp, stably. ⚠ Buffers the entire input — hangs on infinite input.
func (Seq[T]) Step ¶
Step yields the first element and every nth element after it. Panics if n <= 0.
func (Seq[T]) SumOf ¶
SumOf sums the selected values; integer overflow wraps like +. Empty input sums to 0. ⚠ Full drain.
func (Seq[T]) Take ¶
Take yields at most the first n elements, consuming exactly as many as it yields. Panics if n is negative.
func (Seq[T]) TakeLast ¶
TakeLast yields the final n elements. ⚠ Buffers n elements and fully drains the source before emitting — hangs on infinite input. Panics if n is negative.
func (Seq[T]) TallyBy ¶
func (s Seq[T]) TallyBy[K comparable](sel func(T) K) map[K]int
TallyBy counts elements per key. ⚠ Full drain; map iteration order is undefined.
func (Seq[T]) ToChan ¶
ToChan starts a goroutine that sends every element on the returned unbuffered channel. The channel is closed when the sequence ends or ctx is done — the consumer must drain or cancel, or the goroutine leaks.
func (Seq[T]) TopNBy ¶
TopNBy returns the n elements with the largest keys, sorted descending by key; equal keys retain encounter order and the earliest elements win at the cut. Memory is O(n) — the streaming alternative to SortedByDesc().Take(n). ⚠ Full drain. Panics if n is negative.
Example ¶
package main
import (
"fmt"
"github.com/NerdMeNot/catena"
)
func main() {
words := catena.Of("chain", "of", "sequences", "linked", "as", "one")
// Bounded-heap selection: O(3) memory, not a full sort.
fmt.Println(words.TopNBy(3, func(w string) int { return len(w) }))
}
Output: [sequences linked chain]
func (Seq[T]) UntilDone ¶
UntilDone passes elements through until ctx is done, then yields (zero, ctx.Err()) and stops.
func (Seq[T]) Zip ¶
Zip pairs elements of s with elements of other, stopping at the shorter side. The receiver drives; other is consumed through iter.Pull (its cleanup always runs). other is pulled once per emitted pair; the receiver is consumed one element past the pair count when other is shorter.
func (Seq[T]) ZipWithNext ¶
ZipWithNext yields each adjacent pair (element, next element). Empty and single-element input yield nothing.
type Seq2 ¶
Seq2 is a lazy pair sequence: iter.Seq2 with methods. It is a bridge back to Seq (via Keys, Values, MapTo), deliberately not a full peer surface.
func FromMap ¶
func FromMap[K comparable, V any](m map[K]V) Seq2[K, V]
FromMap returns a re-iterable Seq2 over m, in undefined (map) order.
func (Seq2[K, V]) All ¶
All reports whether pred admits every pair; stops at the first counterexample. Vacuously true on empty input.
func (Seq2[K, V]) ForEach ¶
func (s Seq2[K, V]) ForEach(f func(K, V))
ForEach calls f on every pair. ⚠ Full drain.
func (Seq2[K, V]) Keys ¶
Keys yields the first element of each pair. Calling Keys and Values on the same single-pass Seq2 is a double consume — use Unzip.
func (Seq2[K, V]) MapTo ¶
MapTo collapses each pair into one value — the intended exit back to Seq and its full API.
func (Seq2[K, V]) MapValues ¶
MapValues yields each pair with its value replaced by f(k, v). f receives the key too (Kotlin-consistent).
func (Seq2[K, V]) Pull ¶
Pull converts s to a pull-based iterator. THE CALLER MUST CALL stop, even if next has returned false, or resources held by s will leak.
type Try ¶
Try is a lazy sequence of fallible elements: iter.Seq2[T, error] with methods. When err != nil the value must not be read.
func (Try[T]) Collect ¶
Collect gathers successful elements until the first error, returning the partial slice and that error (R5); (all elements, nil) on a clean drain. Nil slice for empty.
Example ¶
package main
import (
"fmt"
"github.com/NerdMeNot/catena"
)
func main() {
nums := catena.Of("1", "2", "x", "4").MapErr(func(s string) (int, error) {
var n int
_, err := fmt.Sscanf(s, "%d", &n)
return n, err
})
// The consumer picks the error policy: stop at the first error...
vals, err := nums.Collect()
fmt.Println(vals, err != nil)
// ...or skip failures and keep going.
fmt.Println(nums.Ignore().Collect())
}
Output: [1 2] true [1 2 4]
func (Try[T]) CollectAll ¶
CollectAll drains everything, gathering all successes and all errors. Positional correspondence between the two slices is lost. Nil slices when empty. ⚠ Full drain.
func (Try[T]) Count ¶
Count counts successful elements up to the first error, which is returned alongside the count so far (R5).
func (Try[T]) Errs ¶
Errs yields the errors, dropping successful elements — the dual of Ignore. Ignore and Errs on the same single-pass Try is a double consume; use CollectAll.
func (Try[T]) Filter ¶
Filter yields the successful elements pred admits; errored elements pass through unexamined.
func (Try[T]) FilterErr ¶
FilterErr yields the successful elements pred admits; a failed pred call yields (zero, err); errored elements pass through unexamined.
func (Try[T]) FlatMap ¶
FlatMap yields every element of f(v) for each successful element v, in order; an errored input element passes through un-mapped.
func (Try[T]) Fold ¶
Fold reduces successful elements until the first error, returning the accumulator so far and that error (R5).
func (Try[T]) ForEach ¶
ForEach calls f on each successful element, stopping at and returning the first of an element error or a non-nil f return (R5).
func (Try[T]) MapErr ¶
MapErr yields f applied to each successful element; a failed call yields (zero, err); errored elements pass through.
func (Try[T]) Must ¶
Must yields the successful elements and panics with the error value on the first error — recover() receives the error itself.
func (Try[T]) OnError ¶
OnError calls f on every error and passes everything through — a logging hook.
func (Try[T]) Pull ¶
Pull converts t to a pull-based iterator. THE CALLER MUST CALL stop, even if next has returned false, or resources held by t will leak.
func (Try[T]) Recover ¶
Recover offers each error to f: reporting true replaces the element with (v, nil); reporting false passes the error through unchanged.
func (Try[T]) Take ¶
Take yields at most the first n elements, errored or not (R2). Panics if n is negative.
func (Try[T]) TakeWhile ¶
TakeWhile yields elements until pred rejects a successful element; errored elements pass through and do not terminate (R3).
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
01-basics
command
Basics: building a pipeline, what laziness means in practice, and how catena sequences interoperate with plain range loops and iter.Seq.
|
Basics: building a pipeline, what laziness means in practice, and how catena sequences interoperate with plain range loops and iter.Seq. |
|
02-grouping
command
Grouping: FoldBy is the library's centerpiece — streaming aggregation bounded by distinct keys, not elements.
|
Grouping: FoldBy is the library's centerpiece — streaming aggregation bounded by distinct keys, not elements. |
|
03-selection
command
Selection: finding extremes and top-k without sorting the world.
|
Selection: finding extremes and top-k without sorting the world. |
|
04-errors
command
Errors: one parse pipeline, three policies.
|
Errors: one parse pipeline, three policies. |
|
05-resources
command
Resources: a producer that owns something — here a real temp file — opens it lazily inside the iteration closure.
|
Resources: a producer that owns something — here a real temp file — opens it lazily inside the iteration closure. |
|
06-streaming
command
Streaming: sequences with no end, and the operators that stay safe on them — running state with Scan, moving averages with Windowed, batching with Chunked, and change detection with DedupeBy.
|
Streaming: sequences with no end, and the operators that stay safe on them — running state with Scan, moving averages with Windowed, batching with Chunked, and change detection with DedupeBy. |
|
07-join
command
Join: JoinBy is a relational inner join between two streams of structs — the right side is indexed by key, the left side streams past it, and the joined stream is a plain Seq you keep chaining on.
|
Join: JoinBy is a relational inner join between two streams of structs — the right side is indexed by key, the left side streams past it, and the joined stream is a plain Seq you keep chaining on. |
|
08-list
command
List and the Seq2 bridge: when the data is small and already in memory, eager evaluation with exact preallocation beats a lazy chain — and the two worlds convert explicitly, in both directions.
|
List and the Seq2 bridge: when the data is small and already in memory, eager evaluation with exact preallocation beats a lazy chain — and the two worlds convert explicitly, in both directions. |
|
internal
|
|
|
gen/listgen
command
Command listgen generates list_gen.go: the eager List[T] mirror of the Seq[T] operation set (§10 of the spec).
|
Command listgen generates list_gen.go: the eager List[T] mirror of the Seq[T] operation set (§10 of the spec). |