diff --git a/README.adoc b/README.adoc index 4a018a5..35e5c4f 100644 --- a/README.adoc +++ b/README.adoc @@ -1,8 +1,8 @@ = Comfy Gopher - Collections image:https://codecov.io/gh/comfygopher/collections/graph/badge.svg?token=I5QQ2SU3E7[codecov,link=https://codecov.io/gh/comfygopher/collections] - -image:https://img.shields.io/coderabbit/prs/github/comfygopher/collections?utm_source=oss&utm_medium=github&utm_campaign=comfygopher%2Fcollections&labelColor=171717&color=FF570A&link=https%3A%2F%2Fcoderabbit.ai&label=CodeRabbit+Reviews[CodeRabbit Pull Request Reviews] +image:https://img.shields.io/coderabbit/prs/github/comfygopher/collections?utm_source=oss&utm_medium=github&utm_campaign=comfygopher%2Fcollections&labelColor=5b5b5b&color=FF570A&link=https%3A%2F%2Fcoderabbit.ai&label=CodeRabbit+Reviews[CodeRabbit Pull Request Reviews] +image:https://goreportcard.com/badge/github.com/comfygopher/collections[Go Report Card,link=https://goreportcard.com/report/github.com/comfygopher/collections] == What is Comfy Gopher? diff --git a/base_cases_test.go b/base_cases_test.go index 5fdac55..ae14aac 100644 --- a/base_cases_test.go +++ b/base_cases_test.go @@ -766,18 +766,18 @@ func getFoldCases(builder baseCollIntBuilder) []*baseTestCase { coll: builder.Empty(), args: baseIntArgs{ reducer: func(acc int, i int, current int) int { - return acc + current + return acc*10 + current }, - initial: 0, + initial: 100, }, - want1: 0, + want1: 100, }, { name: "Fold() on one-item collection", coll: builder.One(), args: baseIntArgs{ reducer: func(acc int, i int, current int) int { - return acc + current + return acc*10 + current }, initial: 0, }, @@ -788,22 +788,22 @@ func getFoldCases(builder baseCollIntBuilder) []*baseTestCase { coll: builder.Three(), args: baseIntArgs{ reducer: func(acc int, i int, current int) int { - return acc + current + return acc*10 + current }, initial: 100, }, - want1: 766, + want1: 113653, }, { name: "Fold() on three-item collection, include index", coll: builder.Three(), args: baseIntArgs{ reducer: func(acc int, i int, current int) int { - return acc + i + current + return acc*(i+1) + current }, initial: 100, }, - want1: 100 + 0 + 111 + 1 + 222 + 2 + 333, + want1: ((100+111)*2+222)*3 + 333, }, } } @@ -820,6 +820,67 @@ func testFold(t *testing.T, builder baseCollIntBuilder) { } } +func getFoldRevCases(builder baseCollIntBuilder) []*baseTestCase { + return []*baseTestCase{ + { + name: "FoldRev() on empty collection", + coll: builder.Empty(), + args: baseIntArgs{ + reducer: func(acc int, _ int, current int) int { + return acc*10 + current + }, + initial: 100, + }, + want1: 100, + }, + { + name: "FoldRev() on one-item collection", + coll: builder.One(), + args: baseIntArgs{ + reducer: func(acc int, _ int, current int) int { + return acc*10 + current + }, + initial: 100, + }, + want1: 1111, + }, + { + name: "FoldRev() on three-item collection", + coll: builder.Three(), + args: baseIntArgs{ + reducer: func(acc int, _ int, current int) int { + return acc*10 + current + }, + initial: 100, + }, + want1: 135631, + }, + { + name: "FoldRev() on three-item collection, include index", + coll: builder.Three(), + args: baseIntArgs{ + reducer: func(acc int, i int, current int) int { + return acc*(i+1) + current + }, + initial: 100, + }, + want1: ((100*3+333)*2 + 222) + 111, + }, + } +} + +func testFoldRev(t *testing.T, builder baseCollIntBuilder) { + cases := getFoldRevCases(builder) + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + got := tt.coll.FoldRev(tt.args.reducer, tt.args.initial) + if !reflect.DeepEqual(got, tt.want1) { + t.Errorf("FoldRev() = %v, want1 %v", got, tt.want1) + } + }) + } +} + func getIsEmptyCases(builder baseCollIntBuilder) []baseTestCase { return []baseTestCase{ { @@ -889,8 +950,8 @@ func getReduceCases(t *testing.T, builder baseCollIntBuilder) []*baseTestCase { { name: "Reduce() on empty collection", coll: builder.Empty(), - args: baseIntArgs{reducer: func(acc int, i int, current int) int { - return acc + current + args: baseIntArgs{reducer: func(acc int, _ int, current int) int { + return acc*10 + current }}, want1: 0, want2: ErrEmptyCollection, @@ -898,8 +959,8 @@ func getReduceCases(t *testing.T, builder baseCollIntBuilder) []*baseTestCase { { name: "Fold() on one-item collection", coll: builder.One(), - args: baseIntArgs{reducer: func(acc int, i int, current int) int { - return acc + current + args: baseIntArgs{reducer: func(acc int, _ int, current int) int { + return acc*10 + current }}, want1: 111, want2: nil, @@ -907,29 +968,67 @@ func getReduceCases(t *testing.T, builder baseCollIntBuilder) []*baseTestCase { { name: "Fold() on three-item collection", coll: builder.Three(), - args: baseIntArgs{reducer: func(acc int, i int, current int) int { - return acc + current + args: baseIntArgs{reducer: func(acc int, _ int, current int) int { + return acc*10 + current }}, - want1: 666, + want1: 13653, want2: nil, }, + } +} + +func testReduce(t *testing.T, builder baseCollIntBuilder) { + cases := getReduceCases(t, builder) + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + got1, got2 := tt.coll.Reduce(tt.args.reducer) + if !reflect.DeepEqual(got1, tt.want1) { + t.Errorf("Reduce() = %v, want1 %v", got1, tt.want1) + } + if !reflect.DeepEqual(got2, tt.want2) { + t.Errorf("Reduce() = %v, want1 %v", got2, tt.want2) + } + }) + } +} + +func getReduceRevCases(t *testing.T, builder baseCollIntBuilder) []*baseTestCase { + return []*baseTestCase{ { - name: "Fold() on three-item collection, include index", + name: "Reduce() on empty collection", + coll: builder.Empty(), + args: baseIntArgs{reducer: func(acc int, _ int, current int) int { + return acc*10 + current + }}, + want1: 0, + want2: ErrEmptyCollection, + }, + { + name: "Fold() on one-item collection", + coll: builder.One(), + args: baseIntArgs{reducer: func(acc int, _ int, current int) int { + return acc*10 + current + }}, + want1: 111, + want2: nil, + }, + { + name: "Fold() on three-item collection", coll: builder.Three(), - args: baseIntArgs{reducer: func(acc int, i int, current int) int { - return acc + i + current + args: baseIntArgs{reducer: func(acc int, _ int, current int) int { + return acc*10 + current }}, - want1: 0 + 111 + 1 + 222 + 2 + 333, + want1: 35631, want2: nil, }, } } -func testReduce(t *testing.T, builder baseCollIntBuilder) { - cases := getReduceCases(t, builder) +func testReduceRev(t *testing.T, builder baseCollIntBuilder) { + cases := getReduceRevCases(t, builder) for _, tt := range cases { t.Run(tt.name, func(t *testing.T) { - got1, got2 := tt.coll.Reduce(tt.args.reducer) + got1, got2 := tt.coll.ReduceRev(tt.args.reducer) if !reflect.DeepEqual(got1, tt.want1) { t.Errorf("Reduce() = %v, want1 %v", got1, tt.want1) } diff --git a/definitions.go b/definitions.go index 0df4eff..50cc1d7 100644 --- a/definitions.go +++ b/definitions.go @@ -58,7 +58,7 @@ type Base[V any] interface { // See: SearchRev FindLast(predicate Predicate[V], defaultValue V) V Fold(reducer Reducer[V], initial V) (result V) - // FoldRev(reducer Reducer[V], initial V) (result V) // TODO + FoldRev(reducer Reducer[V], initial V) (result V) IsEmpty() bool Len() int Search(predicate Predicate[V]) (val V, found bool) @@ -66,7 +66,7 @@ type Base[V any] interface { // SearchPos(predicate Predicate[V]) (val V, found bool) // TODO SearchRev(predicate Predicate[V]) (val V, found bool) Reduce(reducer Reducer[V]) (result V, err error) - // ReduceRev(reducer Reducer[V]) (result V, err error) // TODO + ReduceRev(reducer Reducer[V]) (result V, err error) ToSlice() []V Values() iter.Seq[V] // ValuesRev() iter.Seq[V] // TODO diff --git a/functions.go b/functions.go index f45e29f..c11eaba 100644 --- a/functions.go +++ b/functions.go @@ -1,35 +1,10 @@ package coll -// public API: +// Public: // Copy creates a copy of the given collection. func Copy[C baseInternal[V], V any](c C) C { - //var it V - // - //if _, ok := interface{}(it).(cmp.Cmp); ok { - // // c is of type CmpSequence[V] - //} - return c.copy().(C) - - //switch v := any(c).(type) { - //case *comfySeq[V]: - // return c.copy().(C) - //case *comfyCmpSeq[any]: - // return c.copy().(C) - //} - - // check if c is of type Sequence[C]: - //if cl, ok := any(c).(*comfySeq[V]); ok { - // s := make([]V, len(cl.s)) - // for _, v := range cl.s { - // s = append(s, v) - // } - // c := &comfySeq[V]{ - // s: s, - // } - // return any(c).(C) - //} } //// Filter creates a new, filtered collection from the given collection. @@ -38,6 +13,7 @@ func Copy[C baseInternal[V], V any](c C) C { //} // //// MapTo creates a new, mapped collection from the given collection. +// Maybe this should be called "Transform"? Maybe "MapTo" should be an alias for "Transform"? //func MapTo[OUT Indexed[N], IN Indexed[V], V, N any](coll IN, transformer func(int, V) N) OUT { // panic("not implemented") //} diff --git a/map.go b/map.go index c433a1b..33ad8b6 100644 --- a/map.go +++ b/map.go @@ -126,6 +126,10 @@ func (c *comfyMap[K, V]) Fold(reducer Reducer[Pair[K, V]], initial Pair[K, V]) P return comfyFoldSlice(c.s, reducer, initial) } +func (c *comfyMap[K, V]) FoldRev(reducer Reducer[Pair[K, V]], initial Pair[K, V]) Pair[K, V] { + return comfyFoldSliceRev(c.s, reducer, initial) +} + func (c *comfyMap[K, V]) Get(k K) (V, bool) { pair, ok := c.m[k] if !ok { @@ -202,6 +206,10 @@ func (c *comfyMap[K, V]) Reduce(reducer Reducer[Pair[K, V]]) (Pair[K, V], error) return comfyReduceSlice(c.s, reducer) } +func (c *comfyMap[K, V]) ReduceRev(reducer Reducer[Pair[K, V]]) (Pair[K, V], error) { + return comfyReduceSliceRev(c.s, reducer) +} + func (c *comfyMap[K, V]) Remove(k K) { c.remove(k) } diff --git a/map_cases_test.go b/map_cases_test.go index 1ffa9a8..dcde075 100644 --- a/map_cases_test.go +++ b/map_cases_test.go @@ -1201,29 +1201,51 @@ func getMapFoldCases(builder baseMapCollIntBuilder) []baseMapTestCase { name: "Fold() on empty collection", coll: builder.Empty(), args: baseMapIntArgs{ - reducer: func(acc Pair[int, int], i int, current Pair[int, int]) Pair[int, int] { + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { return acc }, initial: nil, }, want1: nil, }, + { + name: "Fold() on empty collection with initial", + coll: builder.Empty(), + args: baseMapIntArgs{ + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { + return acc + }, + initial: NewPair(10, 100), + }, + want1: NewPair(10, 100), + }, { name: "Fold() on one-item collection", coll: builder.One(), args: baseMapIntArgs{ - reducer: func(acc Pair[int, int], i int, current Pair[int, int]) Pair[int, int] { + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { return current }, initial: nil, }, want1: NewPair(1, 111), }, + { + name: "Fold() on one-item collection with non-nil initial", + coll: builder.One(), + args: baseMapIntArgs{ + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { + return NewPair(acc.Key()+current.Key(), acc.Val()+current.Val()) + }, + initial: NewPair(10, 100), + }, + want1: NewPair(11, 211), + }, { name: "Fold() on three-item collection", coll: builder.Three(), args: baseMapIntArgs{ - reducer: func(acc Pair[int, int], i int, current Pair[int, int]) Pair[int, int] { + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { if acc == nil { return current } @@ -1233,11 +1255,24 @@ func getMapFoldCases(builder baseMapCollIntBuilder) []baseMapTestCase { }, want1: NewPair(6, 666), }, + { + name: "Fold() on three-item collection with non-nil initial", + coll: builder.Three(), + args: baseMapIntArgs{ + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { + newKey := acc.Key() + current.Key() + newVal := acc.Val()*10 + current.Val() + return NewPair(newKey, newVal) + }, + initial: NewPair(10, 100), + }, + want1: NewPair(16, 113653), + }, { name: "Fold() on six-item collection", coll: builder.SixWithDuplicates(), args: baseMapIntArgs{ - reducer: func(acc Pair[int, int], i int, current Pair[int, int]) Pair[int, int] { + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { return NewPair(acc.Key()+current.Key(), acc.Val()+current.Val()) }, initial: NewPair(0, 0), @@ -1259,6 +1294,105 @@ func testMapFold(t *testing.T, builder baseMapCollIntBuilder) { } } +func getMapFoldRevCases(builder baseMapCollIntBuilder) []baseMapTestCase { + return []baseMapTestCase{ + { + name: "Fold() on empty collection", + coll: builder.Empty(), + args: baseMapIntArgs{ + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { + return acc + }, + initial: nil, + }, + want1: nil, + }, + { + name: "Fold() on empty collection with initial", + coll: builder.Empty(), + args: baseMapIntArgs{ + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { + return acc + }, + initial: NewPair(10, 100), + }, + want1: NewPair(10, 100), + }, + { + name: "Fold() on one-item collection", + coll: builder.One(), + args: baseMapIntArgs{ + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { + return current + }, + initial: nil, + }, + want1: NewPair(1, 111), + }, + { + name: "Fold() on one-item collection with non-nil initial", + coll: builder.One(), + args: baseMapIntArgs{ + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { + return NewPair(acc.Key()+current.Key(), acc.Val()+current.Val()) + }, + initial: NewPair(10, 100), + }, + want1: NewPair(11, 211), + }, + { + name: "Fold() on three-item collection", + coll: builder.Three(), + args: baseMapIntArgs{ + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { + if acc == nil { + return current + } + return NewPair(acc.Key()+current.Key(), acc.Val()+current.Val()) + }, + initial: nil, + }, + want1: NewPair(6, 666), + }, + { + name: "Fold() on three-item collection with non-nil initial", + coll: builder.Three(), + args: baseMapIntArgs{ + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { + newKey := acc.Key() + current.Key() + newVal := acc.Val()*10 + current.Val() + return NewPair(newKey, newVal) + }, + initial: NewPair(10, 100), + }, + want1: NewPair(16, 135631), + }, + { + name: "Fold() on six-item collection", + coll: builder.SixWithDuplicates(), + args: baseMapIntArgs{ + reducer: func(acc Pair[int, int], _ int, current Pair[int, int]) Pair[int, int] { + return NewPair(acc.Key()+current.Key(), acc.Val()+current.Val()) + }, + initial: NewPair(0, 0), + }, + want1: NewPair(21, 1332), + }, + } +} + +func testMapFoldRev(t *testing.T, builder baseMapCollIntBuilder) { + cases := getMapFoldRevCases(builder) + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + got := tt.coll.FoldRev(tt.args.reducer, tt.args.initial) + if !reflect.DeepEqual(got, tt.want1) { + t.Errorf("FoldRev() = %v, want1 = %v", got, tt.want1) + } + }) + } +} + func getMapGetCases(builder baseMapCollIntBuilder) []baseMapTestCase { return []baseMapTestCase{ { @@ -1917,30 +2051,30 @@ func testMapPrepend(t *testing.T, builder baseMapCollIntBuilder) { } func getMapReduceCases(builder baseMapCollIntBuilder) []baseMapTestCase { - sumReducer := func(acc Pair[int, int], i int, current Pair[int, int]) Pair[int, int] { - return NewPair(acc.Key()+current.Key(), acc.Val()+current.Val()) + reducer := func(acc Pair[int, int], i int, current Pair[int, int]) Pair[int, int] { + return NewPair(acc.Key()+current.Key(), acc.Val()*10+current.Val()) } return []baseMapTestCase{ { name: "Reduce() on empty collection", coll: builder.Empty(), - args: baseMapIntArgs{reducer: sumReducer}, + args: baseMapIntArgs{reducer: reducer}, want1: nil, want2: ErrEmptyCollection, }, { name: "Reduce() on one-item collection", coll: builder.One(), - args: baseMapIntArgs{reducer: sumReducer}, + args: baseMapIntArgs{reducer: reducer}, want1: NewPair(1, 111), want2: nil, }, { name: "Reduce() on three-item collection", coll: builder.Three(), - args: baseMapIntArgs{reducer: sumReducer}, - want1: NewPair(6, 666), + args: baseMapIntArgs{reducer: reducer}, + want1: NewPair(6, 13653), want2: nil, }, } @@ -1961,6 +2095,51 @@ func testMapReduce(t *testing.T, builder baseMapCollIntBuilder) { } } +func getMapReduceRevCases(builder baseMapCollIntBuilder) []baseMapTestCase { + reducer := func(acc Pair[int, int], i int, current Pair[int, int]) Pair[int, int] { + return NewPair(acc.Key()+current.Key(), acc.Val()*10+current.Val()) + } + + return []baseMapTestCase{ + { + name: "Reduce() on empty collection", + coll: builder.Empty(), + args: baseMapIntArgs{reducer: reducer}, + want1: nil, + want2: ErrEmptyCollection, + }, + { + name: "Reduce() on one-item collection", + coll: builder.One(), + args: baseMapIntArgs{reducer: reducer}, + want1: NewPair(1, 111), + want2: nil, + }, + { + name: "Reduce() on three-item collection", + coll: builder.Three(), + args: baseMapIntArgs{reducer: reducer}, + want1: NewPair(6, 35631), + want2: nil, + }, + } +} + +func testMapReduceRev(t *testing.T, builder baseMapCollIntBuilder) { + cases := getMapReduceRevCases(builder) + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + got1, got2 := tt.coll.ReduceRev(tt.args.reducer) + if !reflect.DeepEqual(got1, tt.want1) { + t.Errorf("Reduce() got1 = %v, want1 = %v", got1, tt.want1) + } + if !reflect.DeepEqual(got2, tt.want2) { + t.Errorf("Reduce() got2 = %v, want2 = %v", got2, tt.want2) + } + }) + } +} + func getMapRemoveCases(builder baseMapCollIntBuilder) []baseMapTestCase { return []baseMapTestCase{ { diff --git a/map_test.go b/map_test.go index f309bd2..dddde4d 100644 --- a/map_test.go +++ b/map_test.go @@ -209,6 +209,10 @@ func Test_comfyMap_Fold(t *testing.T) { testMapFold(t, &comfyMapIntBuilder[mapInternal[int, int]]{}) } +func Test_comfyMap_FoldRev(t *testing.T) { + testMapFoldRev(t, &comfyMapIntBuilder[mapInternal[int, int]]{}) +} + func Test_comfyMap_Get(t *testing.T) { testMapGet(t, &comfyMapIntBuilder[mapInternal[int, int]]{}) } @@ -258,6 +262,10 @@ func Test_comfyMap_Reduce(t *testing.T) { testMapReduce(t, &comfyMapIntBuilder[mapInternal[int, int]]{}) } +func Test_comfyMap_ReduceRev(t *testing.T) { + testMapReduceRev(t, &comfyMapIntBuilder[mapInternal[int, int]]{}) +} + func Test_comfyMap_Remove(t *testing.T) { testMapRemove(t, &comfyMapIntBuilder[mapInternal[int, int]]{}) } diff --git a/mapcmp.go b/mapcmp.go index 5ad0eb0..dc9fe3e 100644 --- a/mapcmp.go +++ b/mapcmp.go @@ -21,8 +21,13 @@ func NewCmpMap[K comparable, V cmp.Ordered]() CmpMap[K, V] { // NewCmpMapFrom creates a new CmpMap instance from a slice of pairs. func NewCmpMapFrom[K comparable, V cmp.Ordered](s []Pair[K, V]) CmpMap[K, V] { - cm := NewCmpMap[K, V]() - cm.(*comfyCmpMap[K, V]).setMany(s) + cm := &comfyCmpMap[K, V]{ + s: []Pair[K, V](nil), + m: make(map[K]Pair[K, V]), + kp: make(map[K]int), + vc: newValuesCounter[V](), + } + cm.setMany(s) return cm } @@ -140,6 +145,10 @@ func (c *comfyCmpMap[K, V]) Fold(reducer Reducer[Pair[K, V]], initial Pair[K, V] return comfyFoldSlice(c.s, reducer, initial) } +func (c *comfyCmpMap[K, V]) FoldRev(reducer Reducer[Pair[K, V]], initial Pair[K, V]) Pair[K, V] { + return comfyFoldSliceRev(c.s, reducer, initial) +} + func (c *comfyCmpMap[K, V]) Get(k K) (V, bool) { pair, ok := c.m[k] if !ok { @@ -246,6 +255,10 @@ func (c *comfyCmpMap[K, V]) Reduce(reducer Reducer[Pair[K, V]]) (Pair[K, V], err return comfyReduceSlice(c.s, reducer) } +func (c *comfyCmpMap[K, V]) ReduceRev(reducer Reducer[Pair[K, V]]) (Pair[K, V], error) { + return comfyReduceSliceRev(c.s, reducer) +} + func (c *comfyCmpMap[K, V]) Remove(k K) { c.remove(k) } diff --git a/mapcmp_test.go b/mapcmp_test.go index 65882ab..4f19071 100644 --- a/mapcmp_test.go +++ b/mapcmp_test.go @@ -237,6 +237,10 @@ func Test_comfyCmpMap_Fold(t *testing.T) { testMapFold(t, &comfyCmpMapIntBuilder[mapInternal[int, int]]{}) } +func Test_comfyCmpMap_FoldRev(t *testing.T) { + testMapFoldRev(t, &comfyCmpMapIntBuilder[mapInternal[int, int]]{}) +} + func Test_comfyCmpMap_Get(t *testing.T) { testMapGet(t, &comfyCmpMapIntBuilder[mapInternal[int, int]]{}) } @@ -306,6 +310,10 @@ func Test_comfyCmpMap_Reduce(t *testing.T) { testMapReduce(t, &comfyCmpMapIntBuilder[mapInternal[int, int]]{}) } +func Test_comfyCmpMap_ReduceRev(t *testing.T) { + testMapReduceRev(t, &comfyCmpMapIntBuilder[mapInternal[int, int]]{}) +} + func Test_comfyCmpMap_Remove(t *testing.T) { testMapRemove(t, &comfyCmpMapIntBuilder[mapInternal[int, int]]{}) } diff --git a/sequence.go b/sequence.go index a1b4022..62ed788 100644 --- a/sequence.go +++ b/sequence.go @@ -128,6 +128,10 @@ func (c *comfySeq[V]) Fold(reducer Reducer[V], initial V) V { return comfyFoldSlice(c.s, reducer, initial) } +func (c *comfySeq[V]) FoldRev(reducer Reducer[V], initial V) V { + return comfyFoldSliceRev(c.s, reducer, initial) +} + func (c *comfySeq[V]) Head() (V, bool) { if len(c.s) == 0 { var v V @@ -173,6 +177,10 @@ func (c *comfySeq[V]) Reduce(reducer Reducer[V]) (V, error) { return comfyReduceSlice(c.s, reducer) } +func (c *comfySeq[V]) ReduceRev(reducer Reducer[V]) (V, error) { + return comfyReduceSliceRev(c.s, reducer) +} + func (c *comfySeq[V]) RemoveAt(i int) (removed V, err error) { if removed, c.s, err = sliceRemoveAt(c.s, i); err != nil { return removed, err diff --git a/sequence_test.go b/sequence_test.go index 5e7431c..b6c4b7a 100644 --- a/sequence_test.go +++ b/sequence_test.go @@ -195,6 +195,10 @@ func Test_comfySeq_Fold(t *testing.T) { testFold(t, &comfySeqIntBuilder[baseInternal[int]]{}) } +func Test_comfySeq_FoldRev(t *testing.T) { + testFoldRev(t, &comfySeqIntBuilder[baseInternal[int]]{}) +} + func Test_comfySeq_Head(t *testing.T) { testHead(t, &comfySeqIntBuilder[linearInternal[int]]{}) } @@ -224,6 +228,10 @@ func Test_comfySeq_Reduce(t *testing.T) { testReduce(t, &comfySeqIntBuilder[baseInternal[int]]{}) } +func Test_comfySeq_ReduceRev(t *testing.T) { + testReduceRev(t, &comfySeqIntBuilder[baseInternal[int]]{}) +} + func Test_comfySeq_RemoveAt(t *testing.T) { testRemoveAt(t, &comfySeqIntBuilder[indexedMutableInternal[int]]{}) } diff --git a/sequencecmp.go b/sequencecmp.go index 1ddf166..4b9e436 100644 --- a/sequencecmp.go +++ b/sequencecmp.go @@ -140,6 +140,10 @@ func (c *comfyCmpSeq[V]) Fold(reducer Reducer[V], initial V) V { return comfyFoldSlice(c.s, reducer, initial) } +func (c *comfyCmpSeq[V]) FoldRev(reducer Reducer[V], initial V) V { + return comfyFoldSliceRev(c.s, reducer, initial) +} + func (c *comfyCmpSeq[V]) HasValue(v V) bool { return c.ContainsValue(v) } @@ -222,6 +226,10 @@ func (c *comfyCmpSeq[V]) Reduce(reducer Reducer[V]) (V, error) { return comfyReduceSlice(c.s, reducer) } +func (c *comfyCmpSeq[V]) ReduceRev(reducer Reducer[V]) (V, error) { + return comfyReduceSliceRev(c.s, reducer) +} + func (c *comfyCmpSeq[V]) RemoveAt(i int) (removed V, err error) { if removed, c.s, err = sliceRemoveAt(c.s, i); err != nil { return removed, err diff --git a/sequencecmp_test.go b/sequencecmp_test.go index 002409d..0b812e9 100644 --- a/sequencecmp_test.go +++ b/sequencecmp_test.go @@ -199,6 +199,10 @@ func Test_comfyCmpSeq_Fold(t *testing.T) { testFold(t, &comfyCmpSeqIntBuilder[baseInternal[int]]{}) } +func Test_comfyCmpSeq_FoldRev(t *testing.T) { + testFoldRev(t, &comfyCmpSeqIntBuilder[baseInternal[int]]{}) +} + func Test_comfyCmpSeq_HasValue(t *testing.T) { testHasValue(t, &comfyCmpSeqIntBuilder[cmpBaseInternal[int, int]]{}) } @@ -282,6 +286,10 @@ func Test_comfyCmpSeq_Reduce(t *testing.T) { testReduce(t, &comfyCmpSeqIntBuilder[baseInternal[int]]{}) } +func Test_comfyCmpSeq_ReduceRev(t *testing.T) { + testReduceRev(t, &comfyCmpSeqIntBuilder[baseInternal[int]]{}) +} + func Test_comfyCmpSeq_RemoveAt(t *testing.T) { testRemoveAt(t, &comfyCmpSeqIntBuilder[indexedMutableInternal[int]]{}) }