Pairs
Seq2 is the standard library’s pairing type with methods — what maps.All and slices.All speak, so every boundary with the standard library is a free conversion. It is deliberately a bridge rather than a peer: it carries what you need to get back to Seq and little else, and MapTo is the intended exit.
Filter
Section titled “Filter”func (s Seq2[K, V]) Filter(pred func(K, V) bool) Seq2[K, V]Filter yields the pairs pred admits.
pairs := catena.Of(1, 2, 3, 4).WithIndex(). Filter(func(i, v int) bool { return v%2 == 0 })fmt.Println(pairs.Values().Collect())[2 4]FilterNot
Section titled “FilterNot”func (s Seq2[K, V]) FilterNot(pred func(K, V) bool) Seq2[K, V]FilterNot yields the pairs pred rejects.
pairs := catena.Of(1, 2, 3).WithIndex(). FilterNot(func(i, v int) bool { return v == 2 })fmt.Println(pairs.Values().Collect())[1 3]func (s Seq2[K, V]) Map[K2, V2 any](f func(K, V) (K2, V2)) Seq2[K2, V2]Map yields f applied to each pair.
pairs := catena.Of("a", "b").WithIndex(). Map(func(i int, s string) (string, int) { return s, i * 10 })fmt.Println(catena.CollectMap(pairs))map[a:0 b:10]MapValues
Section titled “MapValues”func (s Seq2[K, V]) MapValues[V2 any](f func(K, V) V2) Seq2[K, V2]MapValues yields each pair with its value replaced by f(k, v). f receives the key too (Kotlin-consistent).
// The callback receives the key as well as the value.pairs := catena.Of("a", "b").WithIndex(). MapValues(func(i int, s string) string { return fmt.Sprintf("%d%s", i, s) })fmt.Println(pairs.Values().Collect())[0a 1b]func (s Seq2[K, V]) MapTo[U any](f func(K, V) U) Seq[U]MapTo collapses each pair into one value — the intended exit back to Seq and its full API.
// The intended exit: collapse each pair into one value and continue// in Seq, where the full API lives.fmt.Println(catena.Of("a", "b").WithIndex(). MapTo(func(i int, s string) string { return fmt.Sprintf("%d%s", i, s) }). Collect())[0a 1b]func (s Seq2[K, V]) Take(n int) Seq2[K, V]Take yields at most the first n pairs. Panics if n is negative.
fmt.Println(catena.Range(1, 9, 1).WithIndex().Take(3).Values().Collect())[1 2 3]func (s Seq2[K, V]) Drop(n int) Seq2[K, V]Drop skips the first n pairs. Panics if n is negative.
fmt.Println(catena.Range(1, 5, 1).WithIndex().Drop(2).Values().Collect())[3 4]func (s Seq2[K, V]) Keys() Seq[K]Keys yields the first element of each pair. Calling Keys and Values on the same single-pass Seq2 is a double consume — use Unzip.
// Keys and Values on the SAME single-pass Seq2 is a double consume;// Unzip does both in one pass.fmt.Println(catena.Of("a", "b").WithIndex().Keys().Collect())[0 1]Values
Section titled “Values”func (s Seq2[K, V]) Values() Seq[V]Values yields the second element of each pair.
fmt.Println(catena.Of("a", "b").WithIndex().Values().Collect())[a b]func (s Seq2[K, V]) Swap() Seq2[V, K]Swap yields each pair with its sides exchanged.
pairs := catena.Of("a", "b").WithIndex().Swap()fmt.Println(pairs.Keys().Collect())[a b]func (s Seq2[K, V]) Fold[A any](init A, f func(A, K, V) A) AFold reduces the pairs into an accumulator, left to right.
total := catena.Of(10, 20, 30).WithIndex(). Fold(0, func(acc, i, v int) int { return acc + i*v })fmt.Println(total)80ForEach
Section titled “ForEach”func (s Seq2[K, V]) ForEach(f func(K, V))ForEach calls f on every pair.
catena.Of("a", "b").WithIndex().ForEach(func(i int, s string) { fmt.Printf("%d=%s ", i, s)})0=a 1=bfunc (s Seq2[K, V]) Any(pred func(K, V) bool) boolAny reports whether pred admits any pair; stops at the first match.
fmt.Println(catena.Of(1, 2).WithIndex().Any(func(i, v int) bool { return v == 2 }))truefunc (s Seq2[K, V]) All(pred func(K, V) bool) boolAll reports whether pred admits every pair; stops at the first counterexample. Vacuously true on empty input.
fmt.Println(catena.Of(2, 4).WithIndex().All(func(i, v int) bool { return v%2 == 0 }))truefunc (s Seq2[K, V]) Count() intCount returns the number of pairs.
fmt.Println(catena.Of("a", "b", "c").WithIndex().Count())3func (s Seq2[K, V]) First() (K, V, bool)First returns the first pair.
i, v, ok := catena.Of("a", "b").WithIndex().First()fmt.Println(i, v, ok)0 a truefunc (s Seq2[K, V]) Pull() (next func() (K, V, bool), stop func())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.
next, stop := catena.Of("a", "b").WithIndex().Pull()defer stop()i, v, ok := next()fmt.Println(i, v, ok)0 a truefunc (s Seq2[K, V]) Seq2() iter.Seq2[K, V]Seq2 converts to the stdlib iterator type. Free.
for i, v := range catena.Of("a", "b").WithIndex().Seq2() { fmt.Printf("%d=%s ", i, v)}0=a 1=bCollectMap
Section titled “CollectMap”func CollectMap[K comparable, V any](s Seq2[K, V]) map[K]VCollectMap drains a pair sequence into a map; on duplicate keys the last value wins.
// To a map. On a duplicate key the last value wins, as with plain// map assignment.fmt.Println(catena.CollectMap(catena.Of("a", "b").WithIndex()))map[0:a 1:b]func Unzip[K, V any](s Seq2[K, V]) ([]K, []V)Unzip drains a pair sequence into its two sides; nil slices for empty input.
// Both sides in one pass — the safe way to get keys and values from// a single-use Seq2.idx, vals := catena.Unzip(catena.Of("a", "b").WithIndex())fmt.Println(idx, vals)[0 1] [a b]