From 4336b5591bfa4e48f172f64213831bca3dc2f4ce Mon Sep 17 00:00:00 2001 From: Edward Muller Date: Fri, 13 Feb 2026 11:50:25 -0800 Subject: [PATCH 1/3] Add At and AtKV index-based lookup functions #minor Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 2 +- README.md | 2 ++ seq.go | 43 ++++++++++++++++++++++++++++++++++ seq_test.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8876495..980ef65 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -27,4 +27,4 @@ go install honnef.co/go/tools/cmd/staticcheck@latest && staticcheck ./... **Testing**: All tests are `Example` functions — they serve as both documentation and regression tests. No traditional unit tests. Run a single example with `go test -run ExampleFunctionName`. -**Commit tags**: Commit messages use `#patch`, `#minor`, `#major`, or `#none` suffixes for automated semantic version bumping. +**Commit tags**: Commit messages use `#patch`, `#minor`, `#major`, or `#none` suffixes for automated semantic version bumping. Changing the Go version in `go.mod` should use `#minor`. diff --git a/README.md b/README.md index a6170de..7726a8a 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,8 @@ Golang's "missing" iterator/sequence functions. * `FindBy(iter.Seq[T], func(T) bool) (T, int, bool)`: Returns the first value for which the function returns true * `FindByKey(iter.Seq2[K,V], K) (V, int, bool)`: Returns the value of the first key-value pair with the given key * `FindByValue(iter.Seq2[K,V], V) (K, int, bool)`: Returns the key of the first key-value pair with the given value +* `At(iter.Seq[T], int) (T, bool)`: Returns the value at the given 0-based index, or zero value and false if out of range +* `AtKV(iter.Seq2[K,V], int) (K, V, bool)`: Returns the key and value at the given 0-based index, or zero values and false if out of range ## Utility Functions diff --git a/seq.go b/seq.go index 658bb9a..7396311 100644 --- a/seq.go +++ b/seq.go @@ -941,6 +941,49 @@ func MapToKV[T, K, V any](seq iter.Seq[T], fn func(T) (K, V)) iter.Seq2[K, V] { } } +// At returns the value at the given 0-based index in the sequence and true. If +// the index is out of range (negative or beyond sequence length), it returns +// the zero value and false. The provided sequence is iterated over up to and +// including the target index when At is called. +func At[T any](seq iter.Seq[T], index int) (T, bool) { + if index < 0 { + var z T + return z, false + } + var i int + for v := range seq { + if i == index { + return v, true + } + i++ + } + var z T + return z, false +} + +// AtKV returns the key and value at the given 0-based index in the sequence and true. If +// the index is out of range (negative or beyond sequence length), it returns +// the zero values and false. The provided sequence is iterated over up to and +// including the target index when AtKV is called. To find a value by key, use +// FindByKey instead. +func AtKV[K any, V any](seq iter.Seq2[K, V], index int) (K, V, bool) { + if index < 0 { + var zk K + var zv V + return zk, zv, false + } + var i int + for k, v := range seq { + if i == index { + return k, v, true + } + i++ + } + var zk K + var zv V + return zk, zv, false +} + // Find returns the index of the first occurrence of the value in the sequence, the "index" (0 based) of the value, and true. If // the value is not found, the first return value is the length of the sequence, the second return value is false. The provided // sequence is iterated over when Find is called. diff --git a/seq_test.go b/seq_test.go index f5ea771..a725f01 100644 --- a/seq_test.go +++ b/seq_test.go @@ -1026,6 +1026,72 @@ func ExampleMapToKV() { // C 3 } +func ExampleAt() { + i := With(1, 2, 3, 4, 5) + + fmt.Println(At(i, 2)) + + // Output: + // 3 true +} + +func ExampleAt_outOfRange() { + i := With(1, 2, 3) + + fmt.Println(At(i, 5)) + + // Output: + // 0 false +} + +func ExampleAt_empty() { + i := With[int]() + + fmt.Println(At(i, 0)) + + // Output: + // 0 false +} + +func ExampleAt_negative() { + i := With(1, 2, 3) + + fmt.Println(At(i, -1)) + + // Output: + // 0 false +} + +func ExampleAtKV() { + type tKV = KV[string, int] + i := WithKV(tKV{K: "a", V: 1}, tKV{K: "b", V: 2}, tKV{K: "c", V: 3}) + + fmt.Println(AtKV(i, 1)) + + // Output: + // b 2 true +} + +func ExampleAtKV_outOfRange() { + type tKV = KV[string, int] + i := WithKV(tKV{K: "a", V: 1}, tKV{K: "b", V: 2}) + + fmt.Println(AtKV(i, 5)) + + // Output: + // 0 false +} + +func ExampleAtKV_negative() { + type tKV = KV[string, int] + i := WithKV(tKV{K: "a", V: 1}, tKV{K: "b", V: 2}) + + fmt.Println(AtKV(i, -1)) + + // Output: + // 0 false +} + func ExampleFind() { i := With(1, 2, 3, 4, 5) From b95e185288f5efdae650a2a19fd8f505ba0baf9d Mon Sep 17 00:00:00 2001 From: Edward Muller Date: Fri, 13 Feb 2026 11:55:58 -0800 Subject: [PATCH 2/3] Update seq_test.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- seq_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/seq_test.go b/seq_test.go index a725f01..15a0e30 100644 --- a/seq_test.go +++ b/seq_test.go @@ -1092,6 +1092,14 @@ func ExampleAtKV_negative() { // 0 false } +func ExampleAtKV_empty() { + i := WithKV[string, int]() + + fmt.Println(AtKV(i, 0)) + + // Output: + // 0 false +} func ExampleFind() { i := With(1, 2, 3, 4, 5) From 803a06fa9026e0d2ba262bc30a10e4bf00c3c3bb Mon Sep 17 00:00:00 2001 From: Edward Muller Date: Fri, 13 Feb 2026 11:58:01 -0800 Subject: [PATCH 3/3] Retract v0.2.3 #minor Co-Authored-By: Claude Opus 4.6 --- go.mod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.mod b/go.mod index a13e4ce..4f20210 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/freeformz/seq go 1.25 + +retract v0.2.3