diff --git a/.github/workflows/go-format.yml b/.github/workflows/go-format.yml index 8572261..c9306f7 100644 --- a/.github/workflows/go-format.yml +++ b/.github/workflows/go-format.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/setup-go@v2 with: - go-version: '1.18' + go-version: '1.23' - name: Install goimports run: go install golang.org/x/tools/cmd/goimports@latest diff --git a/CHANGELOG.md b/CHANGELOG.md index b0c0bd4..2000a9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ SPDX-License-Identifier: CC-BY-4.0 This project tries to follow [SemVer 2.0.0](https://semver.org/). +## v4.3.1 (WIP) + +- Fixed `slices.Fold` and `slices.FoldReverse` bugs. (#39) + ## v4.3.0 (2023-05-04) - Added `sync2.Map.Len()` method. (#38) diff --git a/slices/slices.go b/slices/slices.go index 35ee457..e01747b 100644 --- a/slices/slices.go +++ b/slices/slices.go @@ -272,7 +272,7 @@ func Filter[S ~[]E, E any](slice S, match func(value E) bool) S { func Fold[S ~[]E, State, E any](slice S, seed State, acc func(state State, value E) State) State { state := seed for _, v := range slice { - seed = acc(state, v) + state = acc(state, v) } return state } @@ -282,8 +282,8 @@ func Fold[S ~[]E, State, E any](slice S, seed State, acc func(state State, value // seed value as-is if the slice is empty. func FoldReverse[S ~[]E, State, E any](slice S, seed State, acc func(state State, value E) State) State { state := seed - for i := len(slice) - 1; i >= 0; i++ { - seed = acc(state, slice[i]) + for i := len(slice) - 1; i >= 0; i-- { + state = acc(state, slice[i]) } return state } diff --git a/slices/slices_test.go b/slices/slices_test.go index d4eba4b..629b848 100755 --- a/slices/slices_test.go +++ b/slices/slices_test.go @@ -188,6 +188,70 @@ func TestRemoveSlice(t *testing.T) { } } +func TestFold(t *testing.T) { + testCases := []struct { + name string + slice []string + seed string + want string + }{ + { + name: "values", + slice: []string{"a", "b", "c"}, + seed: "", + want: "abc", + }, + { + name: "nil slice", + slice: nil, + seed: "seed", + want: "seed", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + gotStr := Fold(tc.slice, tc.seed, func(state string, seed string) string { + return state + seed + }) + if gotStr != tc.want { + t.Errorf("want %q, got %q", tc.want, gotStr) + } + }) + } +} + +func TestFoldReverse(t *testing.T) { + testCases := []struct { + name string + slice []string + seed string + want string + }{ + { + name: "values", + slice: []string{"a", "b", "c"}, + seed: "", + want: "cba", + }, + { + name: "nil slice", + slice: nil, + seed: "seed", + want: "seed", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + gotStr := FoldReverse(tc.slice, tc.seed, func(state string, seed string) string { + return state + seed + }) + if gotStr != tc.want { + t.Errorf("want %q, got %q", tc.want, gotStr) + } + }) + } +} + func TestConcat(t *testing.T) { testCases := []struct { a string