mirror of
https://github.com/rjNemo/underscore
synced 2026-06-06 02:26:42 +00:00
refactor: migrate to Go 1.22 slices/cmp, update linters
Replace usage of golang.org/x/exp/constraints with Go 1.22 cmp/slices. Update .golangci.yml to new v2 format and enable gofmt/goimports. Refactor imports and type constraints across codebase for consistency.
This commit is contained in:
parent
39be9420c4
commit
c53d46816f
14 changed files with 83 additions and 69 deletions
|
|
@ -1,42 +1,54 @@
|
||||||
skip-dirs-use-default: true
|
version: "2"
|
||||||
|
|
||||||
run:
|
|
||||||
timeout: 5m
|
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- bodyclose
|
- bodyclose
|
||||||
- deadcode
|
|
||||||
- depguard
|
- depguard
|
||||||
- dogsled
|
- dogsled
|
||||||
- errcheck
|
|
||||||
- errorlint
|
- errorlint
|
||||||
- exportloopref
|
|
||||||
- gocritic
|
- gocritic
|
||||||
- gocyclo
|
- gocyclo
|
||||||
- gofmt
|
|
||||||
- goimports
|
|
||||||
- goprintffuncname
|
- goprintffuncname
|
||||||
- gosimple
|
|
||||||
- gosec
|
- gosec
|
||||||
- govet
|
|
||||||
- ineffassign
|
|
||||||
- misspell
|
- misspell
|
||||||
- noctx
|
- noctx
|
||||||
- nolintlint
|
- nolintlint
|
||||||
- prealloc
|
- prealloc
|
||||||
- rowserrcheck
|
- rowserrcheck
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- structcheck
|
|
||||||
- stylecheck
|
|
||||||
- typecheck
|
|
||||||
- unconvert
|
- unconvert
|
||||||
- unparam
|
- unparam
|
||||||
- unused
|
|
||||||
- varcheck
|
|
||||||
- whitespace
|
- whitespace
|
||||||
fast: true
|
exclusions:
|
||||||
|
generated: lax
|
||||||
linters-settings:
|
presets:
|
||||||
goimports:
|
- comments
|
||||||
local-prefixes: github.com/rjNemo/underscore
|
- common-false-positives
|
||||||
|
- legacy
|
||||||
|
- std-error-handling
|
||||||
|
paths:
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
|
settings:
|
||||||
|
depguard:
|
||||||
|
rules:
|
||||||
|
main:
|
||||||
|
list-mode: lax
|
||||||
|
files:
|
||||||
|
- $all
|
||||||
|
allow:
|
||||||
|
- $gostd
|
||||||
|
- github.com/rjNemo/underscore
|
||||||
|
- github.com/rjNemo/underscore/...
|
||||||
|
- github.com/stretchr/testify/...
|
||||||
|
- golang.org/x/exp/constraints
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
paths:
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
|
|
|
||||||
9
any.go
9
any.go
|
|
@ -1,12 +1,9 @@
|
||||||
package underscore
|
package underscore
|
||||||
|
|
||||||
|
import "slices"
|
||||||
|
|
||||||
// Any returns true if any of the values in the slice pass the predicate truth test.
|
// Any returns true if any of the values in the slice pass the predicate truth test.
|
||||||
// Short-circuits and stops traversing the slice if a true element is found.
|
// Short-circuits and stops traversing the slice if a true element is found.
|
||||||
func Any[T any](values []T, predicate func(T) bool) bool {
|
func Any[T any](values []T, predicate func(T) bool) bool {
|
||||||
for _, v := range values {
|
return slices.ContainsFunc(values, predicate)
|
||||||
if predicate(v) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDrop(t *testing.T) {
|
func TestDrop(t *testing.T) {
|
||||||
|
|
||||||
nums := []int{1, 9, 2, 8, 3, 7, 4, 6, 5}
|
nums := []int{1, 9, 2, 8, 3, 7, 4, 6, 5}
|
||||||
want := []int{1, 9, 2, 3, 7, 4, 6, 5}
|
want := []int{1, 9, 2, 3, 7, 4, 6, 5}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@ package underscore_test
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
u "github.com/rjNemo/underscore"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
u "github.com/rjNemo/underscore"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFind(t *testing.T) {
|
func TestFind(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@ package underscore_test
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
u "github.com/rjNemo/underscore"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
u "github.com/rjNemo/underscore"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFlatmap(t *testing.T) {
|
func TestFlatmap(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ package underscore_test
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
u "github.com/rjNemo/underscore"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
u "github.com/rjNemo/underscore"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIntersection(t *testing.T) {
|
func TestIntersection(t *testing.T) {
|
||||||
|
|
|
||||||
14
join.go
14
join.go
|
|
@ -6,12 +6,12 @@ func Join[T, P any, S comparable](
|
||||||
left []T,
|
left []T,
|
||||||
right []P,
|
right []P,
|
||||||
leftSelector func(T) S,
|
leftSelector func(T) S,
|
||||||
rightSelector func(P) S) []Tuple[T, []P] {
|
rightSelector func(P) S,
|
||||||
|
) []Tuple[T, []P] {
|
||||||
var results = make([]Tuple[T, []P], 0, len(left))
|
results := make([]Tuple[T, []P], 0, len(left))
|
||||||
for _, l := range left {
|
for _, l := range left {
|
||||||
var matches = Filter(right, func(r P) bool { return leftSelector(l) == rightSelector(r) })
|
matches := Filter(right, func(r P) bool { return leftSelector(l) == rightSelector(r) })
|
||||||
var tuple = Tuple[T, []P]{Left: l, Right: matches}
|
tuple := Tuple[T, []P]{Left: l, Right: matches}
|
||||||
results = append(results, tuple)
|
results = append(results, tuple)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,8 +28,8 @@ func JoinProject[L, R, O any, S comparable](
|
||||||
right []R,
|
right []R,
|
||||||
leftSelector func(L) S,
|
leftSelector func(L) S,
|
||||||
rightSelector func(R) S,
|
rightSelector func(R) S,
|
||||||
projection func(Tuple[L, []R]) O) (results []O) {
|
projection func(Tuple[L, []R]) O,
|
||||||
|
) (results []O) {
|
||||||
for _, x := range Join(left, right, leftSelector, rightSelector) {
|
for _, x := range Join(left, right, leftSelector, rightSelector) {
|
||||||
results = append(results, projection(x))
|
results = append(results, projection(x))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
29
join_test.go
29
join_test.go
|
|
@ -3,23 +3,26 @@ package underscore_test
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
u "github.com/rjNemo/underscore"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
u "github.com/rjNemo/underscore"
|
||||||
)
|
)
|
||||||
|
|
||||||
var zero = u.Tuple[int, string]{Left: 0, Right: "Zero"}
|
var (
|
||||||
var one = u.Tuple[int, string]{Left: 1, Right: "One"}
|
zero = u.Tuple[int, string]{Left: 0, Right: "Zero"}
|
||||||
var two = u.Tuple[int, string]{Left: 2, Right: "Two"}
|
one = u.Tuple[int, string]{Left: 1, Right: "One"}
|
||||||
var three = u.Tuple[int, string]{Left: 3, Right: "Three"}
|
two = u.Tuple[int, string]{Left: 2, Right: "Two"}
|
||||||
|
three = u.Tuple[int, string]{Left: 3, Right: "Three"}
|
||||||
|
)
|
||||||
|
|
||||||
func Test_Join_Can_Join_Two_Slices_Together(t *testing.T) {
|
func Test_Join_Can_Join_Two_Slices_Together(t *testing.T) {
|
||||||
var left = []u.Tuple[int, string]{zero, one, two, three}
|
left := []u.Tuple[int, string]{zero, one, two, three}
|
||||||
var right = []u.Tuple[int, string]{one, three, two, three, two, three}
|
right := []u.Tuple[int, string]{one, three, two, three, two, three}
|
||||||
|
|
||||||
selector := func(x u.Tuple[int, string]) int { return x.Left }
|
selector := func(x u.Tuple[int, string]) int { return x.Left }
|
||||||
|
|
||||||
var joined = u.Join(left, right, selector, selector)
|
joined := u.Join(left, right, selector, selector)
|
||||||
var want = []u.Tuple[u.Tuple[int, string], []u.Tuple[int, string]]{
|
want := []u.Tuple[u.Tuple[int, string], []u.Tuple[int, string]]{
|
||||||
{Left: zero, Right: nil},
|
{Left: zero, Right: nil},
|
||||||
{Left: one, Right: []u.Tuple[int, string]{one}},
|
{Left: one, Right: []u.Tuple[int, string]{one}},
|
||||||
{Left: two, Right: []u.Tuple[int, string]{two, two}},
|
{Left: two, Right: []u.Tuple[int, string]{two, two}},
|
||||||
|
|
@ -30,16 +33,16 @@ func Test_Join_Can_Join_Two_Slices_Together(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Join_Can_Join_and_Project_Two_Slices_Together(t *testing.T) {
|
func Test_Join_Can_Join_and_Project_Two_Slices_Together(t *testing.T) {
|
||||||
var left = []u.Tuple[int, string]{zero, one, two, three}
|
left := []u.Tuple[int, string]{zero, one, two, three}
|
||||||
var right = []u.Tuple[int, string]{one, three, two, three, two, three}
|
right := []u.Tuple[int, string]{one, three, two, three, two, three}
|
||||||
|
|
||||||
selector := func(x u.Tuple[int, string]) int { return x.Left }
|
selector := func(x u.Tuple[int, string]) int { return x.Left }
|
||||||
project := func(x u.Tuple[u.Tuple[int, string], []u.Tuple[int, string]]) int {
|
project := func(x u.Tuple[u.Tuple[int, string], []u.Tuple[int, string]]) int {
|
||||||
return len(x.Right) // projecting to a could of how many
|
return len(x.Right) // projecting to a could of how many
|
||||||
}
|
}
|
||||||
|
|
||||||
var joined = u.JoinProject(left, right, selector, selector, project)
|
joined := u.JoinProject(left, right, selector, selector, project)
|
||||||
var want = []int{0, 1, 2, 3}
|
want := []int{0, 1, 2, 3}
|
||||||
|
|
||||||
assert.Equal(t, want, joined)
|
assert.Equal(t, want, joined)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
max.go
4
max.go
|
|
@ -1,11 +1,11 @@
|
||||||
package underscore
|
package underscore
|
||||||
|
|
||||||
import "golang.org/x/exp/constraints"
|
import "cmp"
|
||||||
|
|
||||||
// Max returns the maximum value in the slice.
|
// Max returns the maximum value in the slice.
|
||||||
// This function can currently only compare numbers reliably.
|
// This function can currently only compare numbers reliably.
|
||||||
// This function uses operator <.
|
// This function uses operator <.
|
||||||
func Max[T constraints.Ordered](values []T) T {
|
func Max[T cmp.Ordered](values []T) T {
|
||||||
max := values[0]
|
max := values[0]
|
||||||
for _, v := range values {
|
for _, v := range values {
|
||||||
if v > max {
|
if v > max {
|
||||||
|
|
|
||||||
4
min.go
4
min.go
|
|
@ -1,11 +1,11 @@
|
||||||
package underscore
|
package underscore
|
||||||
|
|
||||||
import "golang.org/x/exp/constraints"
|
import "cmp"
|
||||||
|
|
||||||
// Min returns the minimum value in the slice.
|
// Min returns the minimum value in the slice.
|
||||||
// This function can currently only compare numbers reliably.
|
// This function can currently only compare numbers reliably.
|
||||||
// This function uses operator <.
|
// This function uses operator <.
|
||||||
func Min[T constraints.Ordered](values []T) T {
|
func Min[T cmp.Ordered](values []T) T {
|
||||||
min := values[0]
|
min := values[0]
|
||||||
for _, v := range values {
|
for _, v := range values {
|
||||||
if v < min {
|
if v < min {
|
||||||
|
|
|
||||||
6
pipe.go
6
pipe.go
|
|
@ -1,10 +1,10 @@
|
||||||
package underscore
|
package underscore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"golang.org/x/exp/constraints"
|
"cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Pipe[T constraints.Ordered] struct {
|
type Pipe[T cmp.Ordered] struct {
|
||||||
Value []T
|
Value []T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12,7 +12,7 @@ type Pipe[T constraints.Ordered] struct {
|
||||||
// call Value to retrieve the final value.
|
// call Value to retrieve the final value.
|
||||||
//
|
//
|
||||||
// Methods not returning a slice such as Reduce, All, Any, will break the Pipe and return Value instantly.
|
// Methods not returning a slice such as Reduce, All, Any, will break the Pipe and return Value instantly.
|
||||||
func NewPipe[T constraints.Ordered](value []T) Pipe[T] {
|
func NewPipe[T cmp.Ordered](value []T) Pipe[T] {
|
||||||
return Pipe[T]{Value: value}
|
return Pipe[T]{Value: value}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package underscore
|
||||||
|
|
||||||
// Result represent the outcome of an operation where failure is possible
|
// Result represent the outcome of an operation where failure is possible
|
||||||
type Result[T any] interface {
|
type Result[T any] interface {
|
||||||
isResult() //to seal the Result interface
|
isResult() // to seal the Result interface
|
||||||
ToValue() (*T, error)
|
ToValue() (*T, error)
|
||||||
IsSuccess() bool
|
IsSuccess() bool
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,19 @@
|
||||||
package underscore
|
package underscore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmp"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"golang.org/x/exp/constraints"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SortSliceASC sorts any slice ASCENDING
|
// SortSliceASC sorts any slice ASCENDING
|
||||||
func SortSliceASC[T constraints.Ordered](s []T) {
|
func SortSliceASC[T cmp.Ordered](s []T) {
|
||||||
sort.SliceStable(s, func(i, j int) bool {
|
sort.SliceStable(s, func(i, j int) bool {
|
||||||
return s[i] < s[j]
|
return s[i] < s[j]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SortSliceDESC sorts any slice DESCENDING
|
// SortSliceDESC sorts any slice DESCENDING
|
||||||
func SortSliceDESC[T constraints.Ordered](s []T) {
|
func SortSliceDESC[T cmp.Ordered](s []T) {
|
||||||
sort.SliceStable(s, func(i, j int) bool {
|
sort.SliceStable(s, func(i, j int) bool {
|
||||||
return s[i] > s[j]
|
return s[i] > s[j]
|
||||||
})
|
})
|
||||||
|
|
|
||||||
8
sum.go
8
sum.go
|
|
@ -1,9 +1,11 @@
|
||||||
package underscore
|
package underscore
|
||||||
|
|
||||||
import "golang.org/x/exp/constraints"
|
import (
|
||||||
|
"cmp"
|
||||||
|
)
|
||||||
|
|
||||||
// Sum adds elements of the slice.
|
// Sum adds elements of the slice.
|
||||||
func Sum[T constraints.Ordered](values []T) (sum T) {
|
func Sum[T cmp.Ordered](values []T) (sum T) {
|
||||||
for _, v := range values {
|
for _, v := range values {
|
||||||
sum += v
|
sum += v
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +14,7 @@ func Sum[T constraints.Ordered](values []T) (sum T) {
|
||||||
|
|
||||||
// SumMap sums the values you select from your struct, basically a sort cut instead of
|
// SumMap sums the values you select from your struct, basically a sort cut instead of
|
||||||
// having to perform a [Map] followed by a [Sum].
|
// having to perform a [Map] followed by a [Sum].
|
||||||
func SumMap[T any, R constraints.Ordered](list []T, selector func(T) R) (sum R) {
|
func SumMap[T any, R cmp.Ordered](list []T, selector func(T) R) (sum R) {
|
||||||
for _, v := range list {
|
for _, v := range list {
|
||||||
sum += selector(v)
|
sum += selector(v)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue