-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5231b03
Showing
19 changed files
with
1,237 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
github: jub0bs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
name: build | ||
|
||
on: [push] | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
go-version: [1.23] | ||
steps: | ||
- name: Check out Source | ||
uses: actions/checkout@v4 | ||
- name: Set up Go ${{ matrix.go-version }} | ||
uses: actions/setup-go@v5 | ||
with: | ||
go-version: ${{ matrix.go-version }} | ||
cache: true | ||
- name: Display Go version | ||
run: go version | ||
- name: Test | ||
run: go test -v -coverprofile=cover.out ./... | ||
- name: Upload coverage reports to Codecov | ||
uses: codecov/codecov-action@v4.0.1 | ||
with: | ||
token: ${{ secrets.CODECOV_TOKEN }} | ||
slug: jub0bs/iterutil | ||
benchmark: | ||
needs: test | ||
strategy: | ||
matrix: | ||
os: [ubuntu-latest] | ||
go-version: [1.23] | ||
name: Benchmark comparison ${{ matrix.os }} @ Go ${{ matrix.go-version }} | ||
runs-on: ${{ matrix.os }} | ||
steps: | ||
- name: Check out Code (previous) | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.base_ref }} | ||
path: previous | ||
- name: Check out Code (new) | ||
uses: actions/checkout@v4 | ||
with: | ||
path: new | ||
- name: Set up Go ${{ matrix.go-version }} | ||
uses: actions/setup-go@v5 | ||
with: | ||
go-version: ${{ matrix.go-version }} | ||
- name: Install benchstat | ||
run: go install golang.org/x/perf/cmd/benchstat@latest | ||
- name: Run Benchmark (previous) | ||
run: | | ||
cd previous | ||
go test -run=^$ -bench=. -count=10 . > benchmark.txt | ||
- name: Run Benchmark (new) | ||
run: | | ||
cd new | ||
go test -run=^$ -bench=. -count=10 . > benchmark.txt | ||
- name: Run benchstat | ||
# Mostly to compare allocations; | ||
# measurements of execution speed in GitHub Actions are unreliable. | ||
run: | | ||
benchstat previous/benchmark.txt new/benchmark.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Changelog | ||
|
||
All notable changes to this project will be documented in this file. | ||
|
||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), | ||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
|
||
## [0.1.0] (2024-09-14) | ||
|
||
[0.1.0]: https://github.com/jub0bs/iterutil/releases/tag/v0.1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Contributing to jub0bs/iterutil | ||
|
||
jub0bs/iterutil is an open-source project | ||
but currently does not accept external contributions. | ||
|
||
However, if you want to report a problem (a bug, a missing feature, | ||
a misfeature, an idea for performance improvement, etc.), | ||
feel free to [open an issue](https://github.com/jub0bs/iterutil/issues/new). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2024 jub0bs | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# jub0bs/iterutil | ||
|
||
[![tag](https://img.shields.io/github/tag/jub0bs/iterutil.svg)](https://github.com/jub0bs/iterutil/releases) | ||
![Go Version](https://img.shields.io/badge/Go-%3E%3D%201.23-%23007d9c) | ||
[![Go Reference](https://pkg.go.dev/badge/github.com/jub0bs/iterutil.svg)](https://pkg.go.dev/github.com/jub0bs/iterutil) | ||
[![license](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat)](https://github.com/jub0bs/iterutil/raw/main/LICENSE) | ||
[![build](https://github.com/jub0bs/iterutil/actions/workflows/iterutil.yml/badge.svg)](https://github.com/jub0bs/iterutil/actions/workflows/iterutil.yml) | ||
[![codecov](https://codecov.io/gh/jub0bs/iterutil/branch/main/graph/badge.svg?token=N208BHWQTM)](https://app.codecov.io/gh/jub0bs/iterutil/tree/main) | ||
[![goreport](https://goreportcard.com/badge/jub0bs/iterutil)](https://goreportcard.com/report/jub0bs/iterutil) | ||
|
||
An experimental collection | ||
(partly inspired by [Haskell][haskell]'s [prelude][prelude]) | ||
of utility functions for working with [Go][golang] [iterators]. | ||
|
||
## Installation | ||
|
||
```shell | ||
go get github.com/jub0bs/iterutil | ||
``` | ||
|
||
jub0bs/iterutil requires Go 1.23 or above. | ||
|
||
## Documentation | ||
|
||
The documentation is available on [pkg.go.dev][pkgsite]. | ||
|
||
## Code coverage | ||
|
||
![coverage](https://codecov.io/gh/jub0bs/iterutil/branch/main/graphs/sunburst.svg?token=N208BHWQTM) | ||
|
||
## License | ||
|
||
All source code is covered by the [MIT License][license]. | ||
|
||
## FAQ | ||
|
||
### Can I depend on this library? | ||
|
||
You can, but at your own peril. As stated above, this library is experimental; | ||
more than anything else, it's an excuse for me to | ||
flex my functional-programming muscles and | ||
familiarize myself with [Go 1.23's iterators][iterators]. | ||
At this early stage, I reserve the right, upon new releases, to break the API: | ||
some functions may see their names and/or signatures change, | ||
and some functions may be removed altogether. | ||
|
||
If you need a few functions from this library but do not want to depend on it, | ||
feel free to copy their sources in your project; | ||
[a little copying is better than a little dependency][copying]. | ||
|
||
### How should I use this library? | ||
|
||
Above all, use it with parsimony. | ||
The functional style displayed by this library is far from ideal in Go, | ||
for several reasons: | ||
|
||
- code readability may suffer, in part | ||
because Go's idiosyncracies hinder a "[fluent interface][fluent]" style and | ||
because Go lacks a concise notation for anonymous functions; | ||
- a more classic and imperative style is likely to prove much more performant; | ||
- Go lacks the powerful [laziness][lazy] of [Haskell][haskell]. | ||
|
||
Bear in mind that the existence of this library is no license | ||
to adopt a functional style all over your codebase! | ||
|
||
[copying]: https://www.youtube.com/watch?v=PAAkCSZUG1c&t=568s | ||
[fluent]: https://en.wikipedia.org/wiki/Fluent_interface | ||
[golang]: https://go.dev/ | ||
[haskell]: https://www.haskell.org/ | ||
[iterators]: https://go.dev/blog/range-functions | ||
[lazy]: https://en.wikipedia.org/wiki/Lazy_evaluation | ||
[license]: https://github.com/jub0bs/iterutil/blob/main/LICENSE | ||
[pkgsite]: https://pkg.go.dev/github.com/jub0bs/iterutil | ||
[prelude]: https://downloads.haskell.org/ghc/9.8.2/docs/libraries/base-4.19.1.0-179c/Prelude.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
## Reporting security issue | ||
|
||
Please do **not** open an issue on GitHub. | ||
Instead, contact jub0bs privately on [Mastodon]. | ||
|
||
[Mastodon]: https://infosec.exchange/@jub0bs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/* | ||
*/ | ||
package iterutil |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package iterutil | ||
|
||
import "iter" | ||
|
||
type ( | ||
bwrapper interface{ Unwrap() []error } | ||
dwrapper interface{ Unwrap() error } | ||
) | ||
|
||
// AllErrors performs a preorder traversal of err and returns an iterator | ||
// over its index-error pairs. For more context, see the [errors] package. | ||
func AllErrors(err error) iter.Seq2[int, error] { | ||
return func(yield func(int, error) bool) { | ||
var i int | ||
if !yield(i, err) { | ||
return | ||
} | ||
i++ | ||
switch err := err.(type) { | ||
case bwrapper: | ||
for _, err := range err.Unwrap() { | ||
for _, err := range AllErrors(err) { | ||
if !yield(i, err) { | ||
return | ||
} | ||
i++ | ||
} | ||
} | ||
case dwrapper: | ||
for _, err := range AllErrors(err.Unwrap()) { | ||
if !yield(i, err) { | ||
return | ||
} | ||
i++ | ||
} | ||
default: | ||
return | ||
} | ||
} | ||
} | ||
|
||
// AllLeafErrors performs a preorder traversal of err and returns an iterator | ||
// over its index-error leaf pairs. For more context, see the [errors] package. | ||
func AllLeafErrors(err error) iter.Seq2[int, error] { | ||
return func(yield func(int, error) bool) { | ||
var i int | ||
switch err := err.(type) { | ||
case bwrapper: | ||
for _, err := range err.Unwrap() { | ||
for _, err := range AllLeafErrors(err) { | ||
if !yield(i, err) { | ||
return | ||
} | ||
i++ | ||
} | ||
} | ||
case dwrapper: | ||
for _, err := range AllLeafErrors(err.Unwrap()) { | ||
if !yield(i, err) { | ||
return | ||
} | ||
i++ | ||
} | ||
default: | ||
if !yield(i, err) { | ||
return | ||
} | ||
i++ | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package iterutil_test | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/jub0bs/iterutil" | ||
) | ||
|
||
func ExampleAllErrors() { | ||
err1 := errors.New("err1") | ||
err2 := fmt.Errorf("err2: %w", err1) | ||
err3 := errors.New("err3") | ||
err4 := errors.New("err4") | ||
err5 := errors.Join(err3, err4) | ||
err := errors.Join(err2, err5) | ||
for i, err := range iterutil.AllErrors(err) { | ||
fmt.Println(i, err) | ||
} | ||
// Output: | ||
// 0 err2: err1 | ||
// err3 | ||
// err4 | ||
// 1 err2: err1 | ||
// 2 err1 | ||
// 3 err3 | ||
// err4 | ||
// 4 err3 | ||
// 5 err4 | ||
} | ||
|
||
func ExampleAllLeafErrors() { | ||
err1 := errors.New("err1") | ||
err2 := fmt.Errorf("err2: %w", err1) | ||
err3 := errors.New("err3") | ||
err4 := errors.New("err4") | ||
err5 := errors.Join(err3, err4) | ||
err := errors.Join(err2, err5) | ||
for i, err := range iterutil.AllLeafErrors(err) { | ||
fmt.Println(i, err) | ||
} | ||
// Output: | ||
// 0 err1 | ||
// 1 err3 | ||
// 2 err4 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/jub0bs/iterutil | ||
|
||
go 1.23.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package iterutil | ||
|
||
import "iter" | ||
|
||
// Left return an iterator composed of the keys of the pairs in seq. | ||
func Left[K, V any](seq iter.Seq2[K, V]) iter.Seq[K] { | ||
return func(yield func(K) bool) { | ||
for k := range seq { | ||
if !yield(k) { | ||
return | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Right return an iterator composed of the values of the pairs in seq. | ||
func Right[K, V any](seq iter.Seq2[K, V]) iter.Seq[V] { | ||
return func(yield func(V) bool) { | ||
for _, v := range seq { | ||
if !yield(v) { | ||
return | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package iterutil_test | ||
|
||
import ( | ||
"fmt" | ||
"slices" | ||
|
||
"github.com/jub0bs/iterutil" | ||
) | ||
|
||
func ExampleLeft() { | ||
seq := slices.All([]string{"zero", "one", "two", "three", "four"}) | ||
for i := range iterutil.Left(seq) { | ||
fmt.Println(i) | ||
} | ||
// Output: | ||
// 0 | ||
// 1 | ||
// 2 | ||
// 3 | ||
// 4 | ||
} | ||
|
||
func ExampleRight() { | ||
seq := slices.All([]string{"zero", "one", "two", "three", "four"}) | ||
for s := range iterutil.Right(seq) { | ||
fmt.Println(s) | ||
} | ||
// Output: | ||
// zero | ||
// one | ||
// two | ||
// three | ||
// four | ||
} |
Oops, something went wrong.