From 465acdfe1e6a35c65b97e9590f08670ca532915f Mon Sep 17 00:00:00 2001 From: kom0055 Date: Wed, 12 Oct 2022 18:40:10 +0800 Subject: [PATCH] simplify api Signed-off-by: kom0055 --- README.MD | 55 ++-- aggregate_test.go | 19 +- benchmark_test.go | 28 +-- concat.go | 76 +++--- concat_test.go | 15 +- defaultifempty.go | 47 ++-- defaultifempty_test.go | 7 +- distinct_test.go | 33 ++- example_test.go | 558 +++++++++++++++++++++-------------------- except_test.go | 10 +- from_test.go | 37 +-- go.mod | 6 +- go.sum | 8 +- groupby_test.go | 6 +- groupjoin_test.go | 8 +- index_test.go | 4 +- intersect_test.go | 10 +- join_test.go | 8 +- orderby_test.go | 25 +- result.go | 11 +- result_test.go | 97 +++---- reverse_test.go | 4 +- select_test.go | 16 +- selectmany_test.go | 40 +-- setup_test.go | 33 --- skip.go | 34 ++- skip_test.go | 23 +- take.go | 28 +-- take_test.go | 24 +- union_test.go | 4 +- utils.go | 21 ++ where.go | 2 +- where_test.go | 16 +- zip_test.go | 6 +- 34 files changed, 649 insertions(+), 670 deletions(-) create mode 100644 utils.go diff --git a/README.MD b/README.MD index 3b29534..576a65b 100644 --- a/README.MD +++ b/README.MD @@ -1,4 +1,5 @@ -# go-flinx +# go-flinx + ## Functional LINQ IN Go [![Sourcegraph](https://sourcegraph.com/github.com/kom0055/go-flinx/-/badge.svg)](https://sourcegraph.com/github.com/kom0055/go-flinx?badge) @@ -11,21 +12,20 @@ Thanks [ahmetb/go-linq](https://github.com/ahmetb/go-linq) for a guidance. Rewrite [ahmetb/go-linq](https://github.com/ahmetb/go-linq) for these reasons: + 1. Not compatible with generics. I've been enough to use type assertions. -2. Low performance when use generic function. You could use generic through function ends with 't', but it's not that efficient and not that elegant. +2. Low performance when use generic function. You could use generic through function ends with 't', but it's not that + efficient and not that elegant. So to solve my problems, I choose to rewrite it using generics and functional-programing. You know that generics in Go is not that flexible, but feature of Currying and Lazy Evaluation could make this. - - ## Installation When used with Go modules, use the following import path: go get github.com/kom0055/go-flinx - ## Quickstart If you were a dotNet/C# developer but a gopher now, you must miss the smooth grammar of LINQ. @@ -34,11 +34,10 @@ If you were a fans of functional-programing but a gopher now, you must be eager Now, you could both enjoy LINQ and functional-programing through this package. - A simple case like below ```go -squares := ToSlice[int](Select[int, int](func(x int) int { return x * x })(Range(1, 10))) +squares := ToSlice(Select(func (x int) int { return x * x })(Range(1, 10))) ``` For more cases, you could visit [example_test.go](example_test.go) @@ -49,36 +48,34 @@ Using ahmetb's go-linq comparison benchmark (see [benchmark_test.go](benchmark_t SelectWhereFirst: -| Lib | Time | -|:------------------------|:-----------------------:| -| go-flinx | 153.4 ns/op | -| go-flink | 162.6 ns/op | -| gp-flink(generics func) | 1043 ns/op | +| Lib | Time | +|:-------------------------|:-----------------------:| +| go-flinx | 153.4 ns/op | +| go-linq | 162.6 ns/op | +| gp-linq(generics func) | 1043 ns/op | Sum: -| Lib | Time | -|:------------------------|:-----------------------:| -| go-flinx | 31092617 ns/op | -| go-flink | 119863792 ns/op | -| gp-flink(generics func) | 2249057541 ns/op | - +| Lib | Time | +|:-------------------------|:----------------:| +| go-flinx | 31092617 ns/op | +| go-linq | 119863792 ns/op | +| gp-linq(generics func) | 2249057541 ns/op | ZipSkipTake: -| Lib | Time | -|:------------------------|:-----------------------:| -| go-flinx | 120.3 ns/op | -| go-flink | 108.4 ns/op | -| gp-flink(generics func) | 562.8 ns/op | - +| Lib | Time | +|:-------------------------|:-----------:| +| go-flinx | 120.3 ns/op | +| go-linq | 108.4 ns/op | +| gp-linq(generics func) | 562.8 ns/op | FromChannel: -| Lib | Time | -|:------------------------|:-----------------------:| -| go-flinx | 1206086167 ns/op | -| go-flink | 1312612709 ns/op | -| gp-flink(from channelt) | 1975103125 ns/op | +| Lib | Time | +|:-------------------------|:----------------:| +| go-flinx | 1206086167 ns/op | +| go-linq | 1312612709 ns/op | +| gp-linq(from channelt) | 1975103125 ns/op | We could make conclusion that if you chase for efficient performance and elegant grammar, go-flinx is a good choice. diff --git a/aggregate_test.go b/aggregate_test.go index f1a8b3b..11de93c 100644 --- a/aggregate_test.go +++ b/aggregate_test.go @@ -1,15 +1,16 @@ package flinx import ( - "gotest.tools/v3/assert" "testing" + + "gotest.tools/v3/assert" ) import "strings" func Test_Aggregate(t *testing.T) { - First[int](Select[int, int](func(i int) int { + First(Select(func(i int) int { return i * 2 - })(Where[int](func(i int) bool { + })(Where(func(i int) bool { return i%2 == 0 })(Range(1, 10)))) @@ -21,7 +22,7 @@ func Test_Aggregate(t *testing.T) { {[]string{}, ""}, } - aggr := Aggregate[string](func(r, i string) string { + aggr := Aggregate(func(r, i string) string { if len(r) > len(i) { return r } @@ -29,7 +30,7 @@ func Test_Aggregate(t *testing.T) { }) for _, test := range tests { - r := aggr(FromSlice[string](test.input)) + r := aggr(FromSlice(test.input)) assert.Equal(t, r, test.want) } @@ -39,13 +40,13 @@ func TestAggregateWithSeed(t *testing.T) { input := []string{"apple", "mango", "orange", "banana", "grape"} want := "passionfruit" - aggr := AggregateWithSeed[string](want, func(r, i string) string { + aggr := AggregateWithSeed(want, func(r, i string) string { if len(r) > len(i) { return r } return i }) - r := aggr(FromSlice[string](input)) + r := aggr(FromSlice(input)) assert.Equal(t, r, want) } @@ -54,7 +55,7 @@ func TestAggregateWithSeedBy(t *testing.T) { input := []string{"apple", "mango", "orange", "passionfruit", "grape"} want := "PASSIONFRUIT" - aggr := AggregateWithSeedBy[string, string]("banana", func(r, i string) string { + aggr := AggregateWithSeedBy("banana", func(r, i string) string { if len(r) > len(i) { return r } @@ -63,7 +64,7 @@ func TestAggregateWithSeedBy(t *testing.T) { func(r string) string { return strings.ToUpper(r) }) - r := aggr(FromSlice[string](input)) + r := aggr(FromSlice(input)) assert.Equal(t, r, want) } diff --git a/benchmark_test.go b/benchmark_test.go index b5853b9..6145280 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -1,8 +1,9 @@ package flinx import ( - "github.com/ahmetb/go-linq/v3" "testing" + + "github.com/ahmetb/go-linq/v3" ) const ( @@ -12,16 +13,15 @@ const ( func BenchmarkSelectWhereFirst(b *testing.B) { b.Run("BenchmarkSelectWhereFirst_flinx", func(b *testing.B) { - selectFn := Select[int](func(i int) int { + selectFn := Select(func(i int) int { return -i }) - whereFn := Where[int](func(i int) bool { + whereFn := Where(func(i int) bool { return i > -5 }) - firstFn := First[int] for n := 0; n < b.N; n++ { - firstFn(whereFn(selectFn(Range(1, size)))) + First(whereFn(selectFn(Range(1, size)))) } }) b.Run("BenchmarkSelectWhereFirst_linq", func(b *testing.B) { @@ -49,12 +49,11 @@ func BenchmarkSelectWhereFirst(b *testing.B) { func BenchmarkSum(b *testing.B) { b.Run("BenchmarkSum_flinx", func(b *testing.B) { - whereFn := Where[int](func(i int) bool { + whereFn := Where(func(i int) bool { return i%2 == 0 }) - sumFn := Sum[int, int] for n := 0; n < b.N; n++ { - sumFn(whereFn(Range(1, size))) + Sum(whereFn(Range(1, size))) } }) @@ -77,19 +76,18 @@ func BenchmarkSum(b *testing.B) { func BenchmarkZipSkipTake(b *testing.B) { b.Run("BenchmarkZipSkipTake_flinx", func(b *testing.B) { - takeFn := Take[int](5) - skipFn := Skip[int](2) - selectFn := Select[int](func(i int) int { + selectFn := Select(func(i int) int { return i * 2 }) - zipFn := Zip[int, int, int](func(i, j int) int { + zipFn := Zip(func(i, j int) int { return i + j }) for n := 0; n < b.N; n++ { - takeFn(skipFn(zipFn(Range(1, size), selectFn(Range(1, size))))) + + Take(Skip(zipFn(Range(1, size), selectFn(Range(1, size))), 2), 5) } }) @@ -116,7 +114,7 @@ func BenchmarkZipSkipTake(b *testing.B) { func BenchmarkFromChannel(b *testing.B) { b.Run("BenchmarkFromChannel_flinx", func(b *testing.B) { - allFn := All[int](func(i int) bool { + allFn := All(func(i int) bool { return true }) @@ -129,7 +127,7 @@ func BenchmarkFromChannel(b *testing.B) { close(ch) }() - allFn(FromChannel[int](ch)) + allFn(FromChannel(ch)) } }) diff --git a/concat.go b/concat.go index d043eb8..a6b9729 100644 --- a/concat.go +++ b/concat.go @@ -2,31 +2,30 @@ package flinx // Append inserts an item to the end of a collection, so it becomes the last // item. -func Append[T any](items ...T) func(q Query[T]) Query[T] { - return func(q Query[T]) Query[T] { - length := len(items) - var defaultValue T - return Query[T]{ - Iterate: func() Iterator[T] { - next := q.Iterate() - index := 0 - - return func() (T, bool) { - i, ok := next() - if ok { - return i, ok - } - if index < length { - idx := index - index++ +func Append[T any](q Query[T], items ...T) Query[T] { - return items[idx], true - } + length := len(items) + var defaultValue T + return Query[T]{ + Iterate: func() Iterator[T] { + next := q.Iterate() + index := 0 + + return func() (T, bool) { + i, ok := next() + if ok { + return i, ok + } + if index < length { + idx := index + index++ - return defaultValue, false + return items[idx], true } - }, - } + + return defaultValue, false + } + }, } } @@ -62,26 +61,25 @@ func Concat[T any](q, q2 Query[T]) Query[T] { // Prepend inserts an item to the beginning of a collection, so it becomes the // first item. -func Prepend[T any](items ...T) func(q Query[T]) Query[T] { - return func(q Query[T]) Query[T] { - length := len(items) - return Query[T]{ - Iterate: func() Iterator[T] { - next := q.Iterate() - index := 0 - - return func() (T, bool) { - if index < length { - idx := index - index++ - return items[idx], true +func Prepend[T any](q Query[T], items ...T) Query[T] { - } + length := len(items) + return Query[T]{ + Iterate: func() Iterator[T] { + next := q.Iterate() + index := 0 + + return func() (T, bool) { + if index < length { + idx := index + index++ + return items[idx], true - return next() } - }, - } + + return next() + } + }, } } diff --git a/concat_test.go b/concat_test.go index 574e9e3..31e97a4 100644 --- a/concat_test.go +++ b/concat_test.go @@ -5,9 +5,8 @@ import "testing" func TestAppend(t *testing.T) { input := []int{1, 2, 3, 4} want := []int{1, 2, 3, 4, 5} - appendFn := Append[int](5) - if q := appendFn(FromSlice[int](input)); !validateQuery[int](q, want) { - t.Errorf("From(%v).Append()=%v expected %v", input, toSlice[int](q), want) + if q := Append(FromSlice(input), 5); !ValidateQuery(q, want) { + t.Errorf("From(%v).Append()=%v expected %v", input, ToSlice(q), want) } } @@ -16,17 +15,15 @@ func TestConcat(t *testing.T) { input2 := []int{4, 5} want := []int{1, 2, 3, 4, 5} - concatFn := Concat[int] - if q := concatFn(FromSlice[int](input1), FromSlice[int](input2)); !validateQuery[int](q, want) { - t.Errorf("From(%v).Concat(%v)=%v expected %v", input1, input2, toSlice(q), want) + if q := Concat(FromSlice(input1), FromSlice(input2)); !ValidateQuery(q, want) { + t.Errorf("From(%v).Concat(%v)=%v expected %v", input1, input2, ToSlice(q), want) } } func TestPrepend(t *testing.T) { input := []int{1, 2, 3, 4} want := []int{0, 1, 2, 3, 4} - prependFn := Prepend[int](0) - if q := prependFn(FromSlice[int](input)); !validateQuery[int](q, want) { - t.Errorf("From(%v).Prepend()=%v expected %v", input, toSlice(q), want) + if q := Prepend(FromSlice(input), 0); !ValidateQuery(q, want) { + t.Errorf("From(%v).Prepend()=%v expected %v", input, ToSlice(q), want) } } diff --git a/defaultifempty.go b/defaultifempty.go index 1259d4d..8a39205 100644 --- a/defaultifempty.go +++ b/defaultifempty.go @@ -2,35 +2,34 @@ package flinx // DefaultIfEmpty returns the elements of the specified sequence // if the sequence is empty. -func DefaultIfEmpty[T any](defaultValue T) func(q Query[T]) Query[T] { - return func(q Query[T]) Query[T] { - return Query[T]{ - Iterate: func() Iterator[T] { - next := q.Iterate() - state := 1 +func DefaultIfEmpty[T any](q Query[T], defaultValue T) Query[T] { - return func() (item T, ok bool) { - switch state { - case 1: - item, ok = next() - if ok { - state = 2 - } else { - item = defaultValue - ok = true - state = -1 - } - return - case 2: - for item, ok = next(); ok; item, ok = next() { - return - } + return Query[T]{ + Iterate: func() Iterator[T] { + next := q.Iterate() + state := 1 + + return func() (item T, ok bool) { + switch state { + case 1: + item, ok = next() + if ok { + state = 2 + } else { + item = defaultValue + ok = true + state = -1 + } + return + case 2: + for item, ok = next(); ok; item, ok = next() { return } return } - }, - } + return + } + }, } } diff --git a/defaultifempty_test.go b/defaultifempty_test.go index 3d84af8..1ee8906 100644 --- a/defaultifempty_test.go +++ b/defaultifempty_test.go @@ -14,12 +14,11 @@ func TestDefaultIfEmpty(t *testing.T) { {[]int{1, 2, 3, 4, 5}, []int{1, 2, 3, 4, 5}}, } - defaltIfEmptyFn := DefaultIfEmpty[int](0) for _, test := range tests { - q := defaltIfEmptyFn(FromSlice(test.input)) + q := DefaultIfEmpty(FromSlice(test.input), 0) - if !validateQuery(q, test.want) { - t.Errorf("From(%v).DefaultIfEmpty(%v)=%v expected %v", test.input, defaultValue, toSlice[int](q), test.want) + if !ValidateQuery(q, test.want) { + t.Errorf("From(%v).DefaultIfEmpty(%v)=%v expected %v", test.input, defaultValue, ToSlice(q), test.want) } } diff --git a/distinct_test.go b/distinct_test.go index d28df63..4c4d8cc 100644 --- a/distinct_test.go +++ b/distinct_test.go @@ -1,8 +1,9 @@ package flinx import ( - "gotest.tools/v3/assert" "testing" + + "gotest.tools/v3/assert" ) func TestDistinct(t *testing.T) { @@ -16,8 +17,8 @@ func TestDistinct(t *testing.T) { } for _, test := range tests { - if q := Distinct[int](FromSlice[int](test.input)); !validateQuery[int](q, test.output) { - t.Errorf("From(%v).Distinct()=%v expected %v", test.input, toSlice(q), test.output) + if q := Distinct(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Distinct()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -26,8 +27,8 @@ func TestDistinct(t *testing.T) { input := "sstr" output := []rune{'s', 't', 'r'} - if q := Distinct[rune](FromString(input)); !validateQuery[rune](q, output) { - t.Errorf("From(%v).Distinct()=%v expected %v", input, toSlice(q), output) + if q := Distinct(FromString(input)); !ValidateQuery(q, output) { + t.Errorf("From(%v).Distinct()=%v expected %v", input, ToSlice(q), output) } } @@ -42,19 +43,18 @@ func TestDistinctForOrderedQuery(t *testing.T) { {[]int{1, 2, 2, 3, 1}, []int{1, 2, 3}}, {[]int{1, 1, 1, 2, 1, 2, 3, 4, 2}, []int{1, 2, 3, 4}}, } - distinctFn := Distinct[int] - orderByFn := OrderBy[int](func(i, j int) int { + orderByFn := OrderBy(func(i, j int) int { return i - j }, func(i int) int { return i }) for _, test := range tests { - if q := distinctFn(FromSlice[int](test.input)); !validateQuery[int](q, test.output) { - t.Errorf("From(%v).Distinct()=%v expected %v", test.input, toSlice(q), test.output) + if q := Distinct(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Distinct()=%v expected %v", test.input, ToSlice(q), test.output) } } for _, test := range tests { - if q := orderByFn(distinctFn(FromSlice[int](test.input))).Query; !validateQuery[int](q, test.output) { - t.Errorf("From(%v).Distinct()=%v expected %v", test.input, toSlice(q), test.output) + if q := orderByFn(Distinct(FromSlice(test.input))).Query; !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Distinct()=%v expected %v", test.input, ToSlice(q), test.output) } } @@ -62,15 +62,14 @@ func TestDistinctForOrderedQuery(t *testing.T) { { - distinctFn := Distinct[rune] - orderByFn := OrderBy[rune](func(i, j rune) int { + orderByFn := OrderBy(func(i, j rune) int { return int(i - j) }, func(i rune) rune { return i }) input := "sstr" output := []rune{'r', 's', 't'} - str := ToString(orderByFn(distinctFn(FromString(input))).Query) + str := ToString(orderByFn(Distinct(FromString(input))).Query) expect := string(output) assert.Equal(t, expect, str) @@ -87,10 +86,10 @@ func TestDistinctBy(t *testing.T) { users := []user{{1, "Foo"}, {2, "Bar"}, {3, "Foo"}} want := []user{{1, "Foo"}, {2, "Bar"}} - distinctByFn := DistinctBy[user, string](func(u user) string { + distinctByFn := DistinctBy(func(u user) string { return u.name }) - if q := distinctByFn(FromSlice[user](users)); !validateQuery[user](q, want) { - t.Errorf("From(%v).DistinctBy()=%v expected %v", users, toSlice(q), want) + if q := distinctByFn(FromSlice(users)); !ValidateQuery(q, want) { + t.Errorf("From(%v).DistinctBy()=%v expected %v", users, ToSlice(q), want) } } diff --git a/example_test.go b/example_test.go index c8b0ee6..4ef27ed 100644 --- a/example_test.go +++ b/example_test.go @@ -2,18 +2,18 @@ package flinx import ( "fmt" - "github.com/kom0055/go-flinx/generics" - "gotest.tools/v3/assert" "strings" "testing" "time" + + "github.com/kom0055/go-flinx/generics" + "gotest.tools/v3/assert" ) func Test_ExampleKeyValue(t *testing.T) { m := make(map[int]bool) m[10] = true - resultFn := Results[KeyValue[int, bool]] - assert.DeepEqual(t, resultFn(FromMap[int, bool](m)), []KeyValue[int, bool]{{10, true}}) + assert.DeepEqual(t, Results(FromMap(m)), []KeyValue[int, bool]{{10, true}}) // Output: // [{10 true}] } @@ -23,7 +23,7 @@ func TestExampleKeyValue_second(t *testing.T) { {10, true}, } - m := ToMap[int, bool](FromSlice[KeyValue[int, bool]](input)) + m := ToMap(FromSlice(input)) assert.DeepEqual(t, m, map[int]bool{10: true}) // Output: @@ -35,7 +35,7 @@ func TestExampleKeyValue_second(t *testing.T) { func TestExampleRange(t *testing.T) { // Generate a slice of integers from 1 to 10 // and then select their squares. - squares := ToSlice[int](Select[int, int](func(x int) int { return x * x })(Range(1, 10))) + squares := ToSlice(Select(func(x int) int { return x * x })(Range(1, 10))) assert.DeepEqual(t, squares, []int{1, 4, 9, 16, 25, 36, 49, 64, 81, 100}) @@ -55,7 +55,7 @@ func TestExampleRange(t *testing.T) { // The following code example demonstrates how to use Repeat // to generate a slice of a repeated value. func TestExampleRepeat(t *testing.T) { - slice := ToSlice[string](Repeat[string]("I like programming.", 5)) + slice := ToSlice(Repeat("I like programming.", 5)) assert.DeepEqual(t, slice, []string{"I like programming.", "I like programming.", "I like programming.", @@ -71,11 +71,11 @@ func TestExampleRepeat(t *testing.T) { } func TestExampleQuery(t *testing.T) { - query := Where[int](func(i int) bool { + query := Where(func(i int) bool { return i <= 3 - })(FromSlice[int]([]int{1, 2, 3, 4, 5})) + })(FromSlice([]int{1, 2, 3, 4, 5})) - slice := ToSlice[int](query) + slice := ToSlice(query) assert.DeepEqual(t, slice, []int{1, 2, 3}) // Output: @@ -87,14 +87,14 @@ func TestExampleQuery(t *testing.T) { // The following code example demonstrates how to use Aggregate function func TestExampleQuery_Aggregate(t *testing.T) { fruits := []string{"apple", "mango", "orange", "passionfruit", "grape"} - aggreFn := Aggregate[string](func(r, i string) string { + aggreFn := Aggregate(func(r, i string) string { if len(r) > len(i) { return r } return i }) // Determine which string in the slice is the longest. - longestName := aggreFn(FromSlice[string](fruits)) + longestName := aggreFn(FromSlice(fruits)) assert.DeepEqual(t, longestName, "passionfruit") // Output: // passionfruit @@ -103,14 +103,14 @@ func TestExampleQuery_Aggregate(t *testing.T) { // The following code example demonstrates how to use AggregateWithSeed function func TestExampleQuery_AggregateWithSeed(t *testing.T) { ints := []int{4, 8, 8, 3, 9, 0, 7, 8, 2} - aggreFn := AggregateWithSeed[int](0, func(total, next int) int { + aggreFn := AggregateWithSeed(0, func(total, next int) int { if next%2 == 0 { return total + 1 } return total }) // Count the even numbers in the array, using a seed value of 0. - numEven := aggreFn(FromSlice[int](ints)) + numEven := aggreFn(FromSlice(ints)) assert.DeepEqual(t, numEven, 6) // Output: // The number of even integers is: 6 @@ -119,7 +119,7 @@ func TestExampleQuery_AggregateWithSeed(t *testing.T) { // The following code example demonstrates how to use AggregateWithSeedBy function func TestExampleQuery_AggregateWithSeedBy(t *testing.T) { input := []string{"apple", "mango", "orange", "passionfruit", "grape"} - aggreFn := AggregateWithSeedBy[string, string]("banana", func(longest, next string) string { + aggreFn := AggregateWithSeedBy("banana", func(longest, next string) string { if len(longest) > len(next) { return longest } @@ -129,7 +129,7 @@ func TestExampleQuery_AggregateWithSeedBy(t *testing.T) { return fmt.Sprintf("The fruit with the longest name is %s.", result) }) // Determine whether any string in the array is longer than "banana". - longestName := aggreFn(FromSlice[string](input)) + longestName := aggreFn(FromSlice(input)) assert.DeepEqual(t, longestName, "The fruit with the longest name is passionfruit.") // Output: // The fruit with the longest name is passionfruit. @@ -139,12 +139,11 @@ func TestExampleQuery_AggregateWithSeedBy(t *testing.T) { // use Distinct to return distinct elements from a slice of integers. func TestExampleOrderedQuery_Distinct(t *testing.T) { ages := []int{21, 46, 46, 55, 17, 21, 55, 55} - distinctFn := Distinct[int] - orderByFn := OrderBy[int, int](generics.NumericCompare[int], func(i int) int { + orderByFn := OrderBy(generics.NumericCompare[int], func(i int) int { return i }) - distinctAges := ToSlice[int](distinctFn(orderByFn(FromSlice[int](ages)).Query)) + distinctAges := ToSlice(Distinct(orderByFn(FromSlice(ages)).Query)) assert.DeepEqual(t, distinctAges, []int{17, 21, 46, 55}) // Output: // [17 21 46 55] @@ -165,16 +164,16 @@ func TestExampleOrderedQuery_DistinctBy(t *testing.T) { {Name: "apple", Code: 9}, } - distinctByFn := DistinctBy[Product, int](func(item Product) int { + distinctByFn := DistinctBy(func(item Product) int { return item.Code }) - orderByFn := OrderBy[Product, string]( + orderByFn := OrderBy( strings.Compare, func(item Product) string { return item.Name }, ) //Order and exclude duplicates. - noduplicates := ToSlice[Product](distinctByFn(orderByFn(FromSlice[Product](products)).Query)) + noduplicates := ToSlice(distinctByFn(orderByFn(FromSlice(products)).Query)) assert.DeepEqual(t, noduplicates, []Product{{Name: "apple", Code: 9}, {Name: "lemon", Code: 12}, {Name: "orange", Code: 4}}) @@ -192,13 +191,13 @@ func TestExampleOrderedQuery_ThenBy(t *testing.T) { // Sort the strings first by their length and then //alphabetically by passing the identity selector function. - thenByFn := ThenBy[string, string](strings.Compare, func(fruit string) string { + thenByFn := ThenBy(strings.Compare, func(fruit string) string { return fruit }) - orderByFn := OrderBy[string, int](generics.NumericCompare[int], func(fruit string) int { + orderByFn := OrderBy(generics.NumericCompare[int], func(fruit string) int { return len(fruit) }) - query := ToSlice[string](thenByFn(orderByFn(FromSlice[string](fruits))).Query) + query := ToSlice(thenByFn(orderByFn(FromSlice(fruits))).Query) assert.DeepEqual(t, query, []string{"apple", "grape", "mango", "banana", "orange", "blueberry", "raspberry", "passionfruit"}) // Output: @@ -231,7 +230,7 @@ func TestExampleQuery_All(t *testing.T) { // Determine whether all pet names // in the array start with 'B'. - allStartWithB := All[Pet](func(pet Pet) bool { return strings.HasPrefix(pet.Name, "B") })(FromSlice[Pet](pets)) + allStartWithB := All(func(pet Pet) bool { return strings.HasPrefix(pet.Name, "B") })(FromSlice(pets)) assert.DeepEqual(t, allStartWithB, false) // Output: // @@ -244,7 +243,7 @@ func TestExampleQuery_Any(t *testing.T) { numbers := []int{1, 2} - hasElements := Any[int](FromSlice[int](numbers)) + hasElements := Any(FromSlice(numbers)) assert.DeepEqual(t, hasElements, true) // Output: // Are there any element in the list? true @@ -267,7 +266,7 @@ func TestExampleQuery_AnyWith(t *testing.T) { } // Determine whether any pets over age 1 are also unvaccinated. - unvaccinated := AnyWith[Pet](func(p Pet) bool { return p.Age > 1 && p.Vaccinated == false })(FromSlice[Pet](pets)) + unvaccinated := AnyWith(func(p Pet) bool { return p.Age > 1 && p.Vaccinated == false })(FromSlice(pets)) assert.DeepEqual(t, unvaccinated, true) // Output: // @@ -279,20 +278,20 @@ func TestExampleQuery_AnyWith(t *testing.T) { func TestExampleQuery_Append(t *testing.T) { input := []int{1, 2, 3, 4} - q := Append[int](5)(FromSlice[int](input)) + q := Append(FromSlice(input), 5) - last, _ := Last[int](q) + last, _ := Last(q) assert.DeepEqual(t, last, 5) // Output: // 5 } -//The following code example demonstrates how to use Average -//to calculate the average of a slice of values. +// The following code example demonstrates how to use Average +// to calculate the average of a slice of values. func TestExampleQuery_Average(t *testing.T) { grades := []int{78, 92, 100, 37, 81} - average := Average[int](FromSlice[int](grades)) + average := Average(FromSlice(grades)) assert.DeepEqual(t, average, 77.6) // Output: @@ -303,7 +302,7 @@ func TestExampleQuery_Average(t *testing.T) { // to count the elements in an array. func TestExampleQuery_Count(t *testing.T) { fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"} - numberOfFruits := Count[string](FromSlice[string](fruits)) + numberOfFruits := Count(FromSlice(fruits)) assert.DeepEqual(t, numberOfFruits, 6) // Output: // 6 @@ -314,19 +313,19 @@ func TestExampleQuery_Count(t *testing.T) { func TestExampleQuery_Contains(t *testing.T) { slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} - has5 := Contains[int](5)(FromSlice[int](slice)) + has5 := Contains(5)(FromSlice(slice)) assert.DeepEqual(t, has5, true) // Output: // Does the slice contains 5? true } -//The following code example demonstrates how to use CountWith -//to count the even numbers in an array. +// The following code example demonstrates how to use CountWith +// to count the even numbers in an array. func TestExampleQuery_CountWith(t *testing.T) { slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} - evenCount := CountWith[int](func(item int) bool { return item%2 == 0 })(FromSlice[int](slice)) + evenCount := CountWith(func(item int) bool { return item%2 == 0 })(FromSlice(slice)) assert.DeepEqual(t, evenCount, 6) // Output: // 6 @@ -373,22 +372,22 @@ func TestExampleQuery_DefaultIfEmpty(t *testing.T) { people := []Person{magnus, terry, charlotte, arlene} pets := []Pet{barley, boots, whiskers, bluemoon, daisy} - groupJoinFn := GroupJoin[Person, Pet, Group[Person, Pet], Person](func(person Person) Person { return person }, + groupJoinFn := GroupJoin(func(person Person) Person { return person }, func(pet Pet) Person { return pet.Owner }, func(person Person, pets []Pet) Group[Person, Pet] { - return Group[Person, Pet]{Key: person, Group: Results[Pet](FromSlice[Pet](pets))} + return Group[Person, Pet]{Key: person, Group: Results(FromSlice(pets))} }) - selectManyByFn := SelectManyBy[Group[Person, Pet], Pet, string]( + selectManyByFn := SelectManyBy( func(g Group[Person, Pet]) Query[Pet] { - return DefaultIfEmpty[Pet](Pet{})(FromSlice[Pet](g.Group)) + return DefaultIfEmpty(FromSlice(g.Group), Pet{}) }, func(pet Pet, group Group[Person, Pet]) string { return fmt.Sprintf("%s: %s", group.Key.FirstName, pet.Name) }, ) - //(FromSlice[Person](people),FromSlice[Pet](pets)) - results := ToSlice[string](selectManyByFn(groupJoinFn(FromSlice[Person](people), FromSlice[Pet](pets)))) + //(FromSlice(people),FromSlice(pets)) + results := ToSlice(selectManyByFn(groupJoinFn(FromSlice(people), FromSlice(pets)))) assert.DeepEqual(t, results, []string{"Magnus: Daisy", "Terry: Barley", "Terry: Boots", "Terry: Blue Moon", "Charlotte: Whiskers", "Arlene: "}) @@ -403,12 +402,12 @@ func TestExampleQuery_DefaultIfEmpty(t *testing.T) { } -//The following code example demonstrates how to use Distinct -//to return distinct elements from a slice of integers. +// The following code example demonstrates how to use Distinct +// to return distinct elements from a slice of integers. func TestExampleQuery_Distinct(t *testing.T) { ages := []int{21, 46, 46, 55, 17, 21, 55, 55} - distinctAges := ToSlice[int](Distinct[int](FromSlice[int](ages))) + distinctAges := ToSlice(Distinct(FromSlice(ages))) assert.DeepEqual(t, distinctAges, []int{21, 46, 55, 17}) // Output: @@ -431,7 +430,7 @@ func TestExampleQuery_DistinctBy(t *testing.T) { } //Order and exclude duplicates. - noduplicates := ToSlice[Product](DistinctBy[Product, int](func(item Product) int { return item.Code })(FromSlice[Product](products))) + noduplicates := ToSlice(DistinctBy(func(item Product) int { return item.Code })(FromSlice(products))) assert.DeepEqual(t, noduplicates, []Product{{Name: "orange", Code: 4}, {Name: "apple", Code: 9}, {Name: "lemon", Code: 12}}) @@ -450,7 +449,7 @@ func TestExampleQuery_Except(t *testing.T) { numbers1 := []float32{2.0, 2.1, 2.2, 2.3, 2.4, 2.5} numbers2 := []float32{2.2} - onlyInFirstSet := ToSlice[float32](Except[float32](FromSlice[float32](numbers1), FromSlice[float32](numbers2))) + onlyInFirstSet := ToSlice(Except(FromSlice(numbers1), FromSlice(numbers2))) assert.DeepEqual(t, onlyInFirstSet, []float32{2, 2.1, 2.3, 2.4, 2.5}) @@ -484,9 +483,9 @@ func TestExampleQuery_ExceptBy(t *testing.T) { } //Order and exclude duplicates. - except := ToSlice[Product](ExceptBy[Product, int](func(item Product) int { + except := ToSlice(ExceptBy(func(item Product) int { return item.Code - })(FromSlice[Product](fruits1), FromSlice[Product](fruits2))) + })(FromSlice(fruits1), FromSlice(fruits2))) assert.DeepEqual(t, except, []Product{{Name: "orange", Code: 4}, {Name: "lemon", Code: 12}}) @@ -500,7 +499,7 @@ func TestExampleQuery_ExceptBy(t *testing.T) { // to return the first element of an array. func TestExampleQuery_First(t *testing.T) { numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19} - n, _ := First[int](FromSlice[int](numbers)) + n, _ := First(FromSlice(numbers)) assert.DeepEqual(t, n, 9) // Output: @@ -508,11 +507,11 @@ func TestExampleQuery_First(t *testing.T) { } -//The following code example demonstrates how to use FirstWith +// The following code example demonstrates how to use FirstWith // to return the first element of an array that satisfies a condition. func TestExampleQuery_FirstWith(t *testing.T) { numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19} - first, _ := FirstWith[int](func(item int) bool { return item > 80 })(FromSlice[int](numbers)) + first, _ := FirstWith(func(item int) bool { return item > 80 })(FromSlice(numbers)) assert.DeepEqual(t, first, 92) // Output: @@ -520,13 +519,13 @@ func TestExampleQuery_FirstWith(t *testing.T) { } -//The following code example demonstrates how to use Intersect -//to return the elements that appear in each of two slices of integers. +// The following code example demonstrates how to use Intersect +// to return the elements that appear in each of two slices of integers. func TestExampleQuery_Intersect(t *testing.T) { id1 := []int{44, 26, 92, 30, 71, 38} id2 := []int{39, 59, 83, 47, 26, 4, 30} - both := ToSlice[int](Intersect[int](FromSlice[int](id1), FromSlice[int](id2))) + both := ToSlice(Intersect(FromSlice(id1), FromSlice(id2))) assert.DeepEqual(t, both, []int{26, 30}) @@ -536,8 +535,8 @@ func TestExampleQuery_Intersect(t *testing.T) { } -//The following code example demonstrates how to use IntersectBy -//to return the elements that appear in each of two slices of products with same Code. +// The following code example demonstrates how to use IntersectBy +// to return the elements that appear in each of two slices of products with same Code. func TestExampleQuery_IntersectBy(t *testing.T) { type Product struct { Name string @@ -554,9 +553,9 @@ func TestExampleQuery_IntersectBy(t *testing.T) { {Name: "apple", Code: 9}, } - duplicates := ToSlice[Product](IntersectBy[Product, int](func(p Product) int { + duplicates := ToSlice(IntersectBy(func(p Product) int { return p.Code - })(FromSlice[Product](store1), FromSlice[Product](store2))) + })(FromSlice(store1), FromSlice(store2))) assert.DeepEqual(t, duplicates, []Product{{Name: "apple", Code: 9}}) @@ -571,7 +570,7 @@ func TestExampleQuery_Last(t *testing.T) { numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 67, 12, 19} - last, _ := Last[int](FromSlice[int](numbers)) + last, _ := Last(FromSlice(numbers)) assert.DeepEqual(t, last, 19) //Output: @@ -585,7 +584,7 @@ func TestExampleQuery_LastWith(t *testing.T) { numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 67, 12, 19} - last, _ := LastWith[int](func(n int) bool { return n > 80 })(FromSlice[int](numbers)) + last, _ := LastWith(func(n int) bool { return n > 80 })(FromSlice(numbers)) assert.DeepEqual(t, last, 87) @@ -599,9 +598,9 @@ func TestExampleQuery_LastWith(t *testing.T) { func TestExampleQuery_Max(t *testing.T) { numbers := []int64{4294967296, 466855135, 81125} - last, _ := Max[int64](func(i, j int64) int { + last, _ := Max(func(i, j int64) int { return int(i - j) - })(FromSlice[int64](numbers)) + })(FromSlice(numbers)) assert.DeepEqual(t, last, int64(4294967296)) //Output: @@ -614,9 +613,9 @@ func TestExampleQuery_Max(t *testing.T) { func TestExampleQuery_Min(t *testing.T) { grades := []int{78, 92, 99, 37, 81} - min, _ := Min[int](func(i, j int) int { + min, _ := Min(func(i, j int) int { return i - j - })(FromSlice[int](grades)) + })(FromSlice(grades)) assert.DeepEqual(t, min, 37) @@ -630,9 +629,9 @@ func TestExampleQuery_Min(t *testing.T) { func TestExampleQuery_OrderByDescending(t *testing.T) { names := []string{"Ned", "Ben", "Susan"} - result := ToSlice[string](OrderByDescending[string, string]( - strings.Compare, getSelf[string], - )(FromSlice[string](names)).Query) + result := ToSlice(OrderByDescending( + strings.Compare, Self[string], + )(FromSlice(names)).Query) assert.DeepEqual(t, result, []string{"Susan", "Ned", "Ben"}) // Output: @@ -642,24 +641,25 @@ func TestExampleQuery_OrderByDescending(t *testing.T) { // The following code example demonstrates how to use ThenByDescending to perform // a secondary ordering of the elements in a slice in descending order. func TestExampleOrderedQuery_ThenByDescending(t *testing.T) { + fruits := []string{"apPLe", "baNanA", "apple", "APple", "orange", "BAnana", "ORANGE", "apPLE"} // Sort the strings first ascending by their length and // then descending using a custom case insensitive comparer. - query := ToSlice[string](ThenByDescending[string, byte](generics.NumericCompare[byte], func(i string) byte { + query := ToSlice(ThenByDescending(generics.NumericCompare[byte], func(i string) byte { return i[0] - })(OrderBy[string, int](generics.NumericCompare[int], func(i string) int { + })(OrderBy(generics.NumericCompare[int], func(i string) int { return len(i) - })(FromSlice[string](fruits))).Query) + })(FromSlice(fruits))).Query) - assert.DeepEqual(t, query, []string{"apPLe", "apPLE", "apple", "APple", "orange", "baNanA", "ORANGE", "BAnana"}) + assert.DeepEqual(t, query, []string{"apPLe", "apple", "apPLE", "APple", "orange", "baNanA", "ORANGE", "BAnana"}) // Output: // apPLe - // apPLE // apple + // apPLE // APple // orange // baNanA @@ -671,7 +671,7 @@ func TestExampleOrderedQuery_ThenByDescending(t *testing.T) { // The following code example demonstrates how to use Concat // to concatenate two slices. func TestExampleQuery_Concat(t *testing.T) { - assert.DeepEqual(t, Results[int](Concat[int](FromSlice[int]([]int{1, 2, 3}), FromSlice[int]([]int{4, 5, 6}))), + assert.DeepEqual(t, Results(Concat(FromSlice([]int{1, 2, 3}), FromSlice([]int{4, 5, 6}))), []int{1, 2, 3, 4, 5, 6}) // Output: // [1 2 3 4 5 6] @@ -679,13 +679,13 @@ func TestExampleQuery_Concat(t *testing.T) { func TestExampleQuery_GroupBy(t *testing.T) { input := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} - res := Results[Group[int, int]](OrderBy[Group[int, int], int](func(i, j int) int { + res := Results(OrderBy(func(i, j int) int { return i - j }, func(g Group[int, int]) int { return g.Key - })(GroupBy[int, int](func(i int) int { return i % 2 }, func(i int) int { + })(GroupBy(func(i int) int { return i % 2 }, func(i int) int { return i - })(FromSlice[int](input))).Query) + })(FromSlice(input))).Query) assert.DeepEqual(t, res, []Group[int, int]{{Key: 0, Group: []int{2, 4, 6, 8}}, {Key: 1, Group: []int{1, 3, 5, 7, 9}}}) @@ -703,13 +703,13 @@ func TestExampleQuery_GroupJoin(t *testing.T) { "cherry", "clementine", } - res := Results[KeyValue[rune, []string]](GroupJoin[rune, string, KeyValue[rune, []string], rune]( + res := Results(GroupJoin( func(i rune) rune { return i }, func(i string) rune { return []rune(i)[0] }, func(outer rune, inners []string) KeyValue[rune, []string] { return KeyValue[rune, []string]{outer, inners} }, - )(FromString("abc"), FromSlice[string](fruits))) + )(FromString("abc"), FromSlice(fruits))) assert.DeepEqual(t, res, []KeyValue[rune, []string]{{Key: 'a', Value: []string{"apple", "apricot"}}, {Key: 'b', Value: []string{"banana"}}, @@ -745,9 +745,9 @@ func TestExampleQuery_IndexOf(t *testing.T) { }, } - index := IndexOf[Item](func(item Item) bool { + index := IndexOf(func(item Item) bool { return item.Name == "Rickster" - })(FromSlice[Item](items)) + })(FromSlice(items)) assert.DeepEqual(t, index, 2) if index >= 0 { @@ -771,17 +771,17 @@ func TestExampleQuery_Join(t *testing.T) { } q := - Join[int, string, KeyValue[int, string], int]( - getSelf[int], + Join( + Self[int], func(i string) int { return len(i) }, func(outer int, inner string) KeyValue[int, string] { return KeyValue[int, string]{outer, inner} }, - )(Range(1, 10), FromSlice[string](fruits)) + )(Range(1, 10), FromSlice(fruits)) - assert.DeepEqual(t, Results[KeyValue[int, string]](q), []KeyValue[int, string]{ + assert.DeepEqual(t, Results(q), []KeyValue[int, string]{ {Key: 5, Value: "apple"}, {Key: 6, Value: "banana"}, {Key: 6, Value: "cherry"}, {Key: 7, Value: "apricot"}, {Key: 10, Value: "clementine"}, }) @@ -793,17 +793,17 @@ func TestExampleQuery_Join(t *testing.T) { // to sort the elements of a slice. func TestExampleQuery_OrderBy(t *testing.T) { - q := ThenByDescending[int]( + q := ThenByDescending( generics.NumericCompare[int], - getSelf[int], - )(OrderBy[int, int]( + Self[int], + )(OrderBy( generics.NumericCompare[int], func(v int) int { return v % 2 }, )(Range(1, 10))) - assert.DeepEqual(t, Results[int](q.Query), []int{10, 8, 6, 4, 2, 9, 7, 5, 3, 1}) + assert.DeepEqual(t, Results(q.Query), []int{10, 8, 6, 4, 2, 9, 7, 5, 3, 1}) // Output: // [10 8 6 4 2 9 7 5 3 1] } @@ -813,7 +813,7 @@ func TestExampleQuery_OrderBy(t *testing.T) { func TestExampleQuery_Prepend(t *testing.T) { input := []int{2, 3, 4, 5} - first, _ := First[int](Prepend[int](1)(FromSlice[int](input))) + first, _ := First(Prepend(FromSlice(input), 1)) assert.DeepEqual(t, first, 1) // Output: // 1 @@ -824,7 +824,7 @@ func TestExampleQuery_Prepend(t *testing.T) { func TestExampleQuery_Reverse(t *testing.T) { input := "apple" - output := ToSlice[rune](Reverse[rune](FromString(input))) + output := ToSlice(Reverse(FromString(input))) assert.DeepEqual(t, string(output), "elppa") // Output: @@ -834,7 +834,7 @@ func TestExampleQuery_Reverse(t *testing.T) { // The following code example demonstrates how to use Select // to project over a slice of values. func TestExampleQuery_Select(t *testing.T) { - squares := ToSlice[int](Select[int, int](func(x int) int { + squares := ToSlice(Select(func(x int) int { return x * x })(Range(1, 10))) @@ -846,9 +846,9 @@ func TestExampleQuery_Select(t *testing.T) { func TestExampleQuery_SelectMany(t *testing.T) { input := [][]int{{1, 2, 3}, {4, 5, 6, 7}} - res := Results[int](SelectMany[[]int, int](func(i []int) Query[int] { - return FromSlice[int](i) - })(FromSlice[[]int](input))) + res := Results(SelectMany(func(i []int) Query[int] { + return FromSlice(i) + })(FromSlice(input))) assert.DeepEqual(t, res, []int{1, 2, 3, 4, 5, 6, 7}) // Output: @@ -860,9 +860,9 @@ func TestExampleQuery_SelectMany(t *testing.T) { func TestExampleQuery_SelectIndexed(t *testing.T) { fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"} - result := ToSlice[string](SelectIndexed[string, string](func(i int, s string) string { + result := ToSlice(SelectIndexed(func(i int, s string) string { return s[:i] - })(FromSlice[string](fruits))) + })(FromSlice(fruits))) assert.DeepEqual(t, result, []string{"", "b", "ma", "ora", "pass", "grape"}) // Output: @@ -898,17 +898,17 @@ func TestExampleQuery_SelectManyByIndexed(t *testing.T) { people := []Person{magnus, terry, charlotte} - results := ToSlice[string](SelectManyByIndexed[Person, string, string]( + results := ToSlice(SelectManyByIndexed( func(i int, p Person) Query[string] { - return Select[Pet, string](func(pet Pet) string { + return Select(func(pet Pet) string { return fmt.Sprintf("%d - %s", i, pet.Name) - })(FromSlice[Pet](p.Pets)) + })(FromSlice(p.Pets)) }, func(pet string, person Person) string { return fmt.Sprintf("Pet: %s, Owner: %s", pet, person.Name) }, - )(FromSlice[Person](people))) + )(FromSlice(people))) assert.DeepEqual(t, results, []string{"Pet: 0 - Daisy, Owner: Hedlund, Magnus", "Pet: 1 - Barley, Owner: Adams, Terry", @@ -957,15 +957,15 @@ func TestExampleQuery_SelectManyIndexed(t *testing.T) { logFiles := []LogFile{file1, file2, file3} - results := ToSlice[string](SelectManyIndexed[LogFile, string]( + results := ToSlice(SelectManyIndexed( func(fileIndex int, file LogFile) Query[string] { - return SelectIndexed[string, string]( + return SelectIndexed( func(lineIndex int, line string) string { return fmt.Sprintf("File:[%d] - %s => line: %d - %s", fileIndex+1, file.Name, lineIndex+1, line) }, - )(FromSlice[string](file.Lines)) + )(FromSlice(file.Lines)) }, - )(FromSlice[LogFile](logFiles))) + )(FromSlice(logFiles))) assert.DeepEqual(t, results, []string{ "File:[1] - file1.log => line: 1 - INFO: 2013/11/05 18:11:01 main.go:44: Special Information", @@ -1011,14 +1011,14 @@ func TestExampleQuery_SelectManyBy(t *testing.T) { } people := []Person{magnus, terry, charlotte} - results := ToSlice[string](SelectManyBy[Person, Pet, string]( + results := ToSlice(SelectManyBy( func(person Person) Query[Pet] { - return FromSlice[Pet](person.Pets) + return FromSlice(person.Pets) }, func(pet Pet, person Person) string { return fmt.Sprintf("Owner: %s, Pet: %s", person.Name, pet.Name) }, - )(FromSlice[Person](people))) + )(FromSlice(people))) assert.DeepEqual(t, results, []string{"Owner: Hedlund, Magnus, Pet: Daisy", "Owner: Adams, Terry, Pet: Barley", @@ -1054,7 +1054,7 @@ func TestExampleQuery_SequenceEqual(t *testing.T) { {Name: "Daisy", Age: 4}, } - equal := SequenceEqual[Pet](FromSlice[Pet](pets1), FromSlice[Pet](pets2)) + equal := SequenceEqual(FromSlice(pets1), FromSlice(pets2)) assert.DeepEqual(t, equal, true) // Output: // Are the lists equals? true @@ -1065,7 +1065,7 @@ func TestExampleQuery_SequenceEqual(t *testing.T) { func TestExampleQuery_Single(t *testing.T) { fruits1 := []string{"orange"} - fruit1, _ := Single[string](FromSlice[string](fruits1)) + fruit1, _ := Single(FromSlice(fruits1)) assert.DeepEqual(t, fruit1, "orange") // Output: @@ -1077,7 +1077,7 @@ func TestExampleQuery_Single(t *testing.T) { func TestExampleQuery_SingleWith(t *testing.T) { fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"} - fruit, _ := SingleWith[string](func(f string) bool { return len(f) > 10 })(FromSlice[string](fruits)) + fruit, _ := SingleWith(func(f string) bool { return len(f) > 10 })(FromSlice(fruits)) assert.DeepEqual(t, fruit, "passionfruit") // Output: @@ -1089,13 +1089,14 @@ func TestExampleQuery_SingleWith(t *testing.T) { // and return the remaining elements. func TestExampleQuery_Skip(t *testing.T) { grades := []int{59, 82, 70, 56, 92, 98, 85} - lowerGrades := ToSlice[int]( + lowerGrades := ToSlice( - Skip[int](3)( - OrderByDescending[int, int]( + Skip( + OrderByDescending( generics.NumericCompare[int], func(g int) int { return g }, - )(FromSlice[int](grades)).Query, + )(FromSlice(grades)).Query, + 3, ), ) @@ -1110,13 +1111,13 @@ func TestExampleQuery_Skip(t *testing.T) { func TestExampleQuery_SkipWhile(t *testing.T) { grades := []int{59, 82, 70, 56, 92, 98, 85} - lowerGrades := ToSlice[int]( + lowerGrades := ToSlice( - SkipWhile[int](func(g int) bool { return g >= 80 })( - OrderByDescending[int, int]( + SkipWhile(func(g int) bool { return g >= 80 })( + OrderByDescending( generics.NumericCompare[int], func(g int) int { return g }, - )(FromSlice[int](grades)).Query, + )(FromSlice(grades)).Query, ), ) @@ -1133,8 +1134,8 @@ func TestExampleQuery_SkipWhile(t *testing.T) { func TestExampleQuery_SkipWhileIndexed(t *testing.T) { amounts := []int{5000, 2500, 9000, 8000, 6500, 4000, 1500, 5500} - query := ToSlice[int]( - SkipWhileIndexed[int](func(index int, amount int) bool { return amount > index*1000 })(FromSlice[int](amounts)), + query := ToSlice( + SkipWhileIndexed(func(index int, amount int) bool { return amount > index*1000 })(FromSlice(amounts)), ) assert.DeepEqual(t, query, []int{4000, 1500, 5500}) @@ -1148,8 +1149,8 @@ func TestExampleQuery_SkipWhileIndexed(t *testing.T) { func TestExampleQuery_Sort(t *testing.T) { amounts := []int{5000, 2500, 9000, 8000, 6500, 4000, 1500, 5500} - query := ToSlice[int]( - Sort[int](func(i, j int) bool { return i < j })(FromSlice[int](amounts)), + query := ToSlice( + Sort(func(i, j int) bool { return i < j })(FromSlice(amounts)), ) assert.DeepEqual(t, query, []int{1500, 2500, 4000, 5000, 5500, 6500, 8000, 9000}) @@ -1162,7 +1163,7 @@ func TestExampleQuery_Sort(t *testing.T) { // to sum the values of a slice. func TestExampleQuery_SumFloats(t *testing.T) { numbers := []float64{43.68, 1.25, 583.7, 6.5} - sum := Sum[float64, float64](FromSlice[float64](numbers)) + sum := Sum(FromSlice(numbers)) assert.DeepEqual(t, sum, 635.130000) // Output: // The sum of the numbers is 635.130000. @@ -1174,7 +1175,7 @@ func TestExampleQuery_SumFloats(t *testing.T) { func TestExampleQuery_SumInts(t *testing.T) { numbers := []int{43, 1, 583, 6} - sum := Sum[int, int](FromSlice[int](numbers)) + sum := Sum(FromSlice(numbers)) assert.DeepEqual(t, sum, 633) // Output: @@ -1187,7 +1188,7 @@ func TestExampleQuery_SumInts(t *testing.T) { func TestExampleQuery_SumUInts(t *testing.T) { numbers := []uint{43, 1, 583, 6} - sum := Sum[uint, uint](FromSlice[uint](numbers)) + sum := Sum(FromSlice(numbers)) assert.DeepEqual(t, sum, uint(633)) // Output: @@ -1196,12 +1197,13 @@ func TestExampleQuery_SumUInts(t *testing.T) { } // The following code example demonstrates how to use Take -// to return elements from the start of a slice. +// +// to return elements from the start of a slice. func TestExampleQuery_Take(t *testing.T) { grades := []int{59, 82, 70, 56, 92, 98, 85} - topThreeGrades := ToSlice[int]( - Take[int](3)(OrderByDescending[int, int](generics.NumericCompare[int], func(g int) int { return g })(FromSlice[int](grades)).Query), + topThreeGrades := ToSlice( + Take(OrderByDescending(generics.NumericCompare[int], func(g int) int { return g })(FromSlice(grades)).Query, 3), ) assert.DeepEqual(t, topThreeGrades, []int{98, 92, 85}) @@ -1214,7 +1216,7 @@ func TestExampleQuery_Take(t *testing.T) { func TestExampleQuery_TakeWhile(t *testing.T) { fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"} - query := ToSlice[string](TakeWhile[string](func(fruit string) bool { return fruit != "orange" })(FromSlice[string](fruits))) + query := ToSlice(TakeWhile(func(fruit string) bool { return fruit != "orange" })(FromSlice(fruits))) assert.DeepEqual(t, query, []string{"apple", "banana", "mango"}) // Output: @@ -1229,9 +1231,9 @@ func TestExampleQuery_TakeWhileIndexed(t *testing.T) { fruits := []string{"apple", "passionfruit", "banana", "mango", "orange", "blueberry", "grape", "strawberry"} - query := ToSlice[string](TakeWhileIndexed[string]( + query := ToSlice(TakeWhileIndexed( func(index int, fruit string) bool { return len(fruit) >= index }, - )(FromSlice[string](fruits))) + )(FromSlice(fruits))) assert.DeepEqual(t, query, []string{"apple", "passionfruit", "banana", "mango", "orange", "blueberry"}) // Output: @@ -1244,7 +1246,7 @@ func TestExampleQuery_ToChannel(t *testing.T) { c := make(chan int) go func() { - ToChannel[int](Repeat(10, 3), c) + ToChannel(Repeat(10, 3), c) }() for i := range c { @@ -1261,7 +1263,7 @@ func TestExampleQuery_ToChannel(t *testing.T) { func TestExampleQuery_ToChannelT(t *testing.T) { c := make(chan string) - go ToChannel[string](Repeat("ten", 3), c) + go ToChannel(Repeat("ten", 3), c) for i := range c { assert.DeepEqual(t, i, "ten") @@ -1286,11 +1288,11 @@ func TestExampleQuery_ToMap(t *testing.T) { {Name: "apple", Code: 9}, } - map1 := ToMap[int, string](Select[Product, KeyValue[int, string]]( + map1 := ToMap(Select( func(item Product) KeyValue[int, string] { return KeyValue[int, string]{Key: item.Code, Value: item.Name} }, - )(FromSlice[Product](products))) + )(FromSlice(products))) assert.DeepEqual(t, map1, map[int]string{4: "orange", 9: "apple", 12: "lemon"}) @@ -1305,13 +1307,13 @@ func TestExampleQuery_ToMap(t *testing.T) { func TestExampleQuery_ToMapBy(t *testing.T) { input := [][]any{{1, true}} - result := ToMapBy[int, bool, []any](func(t []any) int { + result := ToMapBy(func(t []any) int { return t[0].(int) }, func(t []any) bool { return t[1].(bool) }, - )(FromSlice[[]any](input)) + )(FromSlice(input)) assert.DeepEqual(t, result, map[int]bool{1: true}) // Output: @@ -1320,7 +1322,7 @@ func TestExampleQuery_ToMapBy(t *testing.T) { // The following code example demonstrates how to use ToSlice to populate a slice. func TestExampleQuery_ToSlice(t *testing.T) { - result := ToSlice[int](Range(1, 10)) + result := ToSlice(Range(1, 10)) assert.DeepEqual(t, result, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) // Output: // [1 2 3 4 5 6 7 8 9 10] @@ -1329,7 +1331,7 @@ func TestExampleQuery_ToSlice(t *testing.T) { // The following code example demonstrates how to use Union // to obtain the union of two slices of integers. func TestExampleQuery_Union(t *testing.T) { - q := Results[int](Union(Range(1, 10), Range(6, 10))) + q := Results(Union(Range(1, 10), Range(6, 10))) assert.DeepEqual(t, q, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) @@ -1342,9 +1344,9 @@ func TestExampleQuery_Union(t *testing.T) { func TestExampleQuery_Where(t *testing.T) { fruits := []string{"apple", "passionfruit", "banana", "mango", "orange", "blueberry", "grape", "strawberry"} - query := ToSlice[string](Where[string](func(f string) bool { + query := ToSlice(Where(func(f string) bool { return len(f) > 6 - })(FromSlice[string](fruits))) + })(FromSlice(fruits))) assert.DeepEqual(t, query, []string{"passionfruit", "blueberry", "strawberry"}) @@ -1356,9 +1358,9 @@ func TestExampleQuery_Where(t *testing.T) { // to filter a slice based on a predicate that involves the index of each element. func TestExampleQuery_WhereIndexed(t *testing.T) { numbers := []int{0, 30, 20, 15, 90, 85, 40, 75} - query := ToSlice[int](WhereIndexed[int](func(index, number int) bool { + query := ToSlice(WhereIndexed(func(index, number int) bool { return number <= index*10 - })(FromSlice[int](numbers))) + })(FromSlice(numbers))) assert.DeepEqual(t, query, []int{0, 20, 15, 40}) // Output: @@ -1371,12 +1373,12 @@ func TestExampleQuery_Zip(t *testing.T) { number := []int{1, 2, 3, 4, 5} words := []string{"one", "two", "three"} - q := Zip[int, string, []any](func(a int, b string) []any { + q := Zip(func(a int, b string) []any { return []any{a, b} })( - FromSlice[int](number), FromSlice[string](words), + FromSlice(number), FromSlice(words), ) - assert.DeepEqual(t, ToSlice[[]any](q), [][]any{{1, "one"}, {2, "two"}, {3, "three"}}) + assert.DeepEqual(t, ToSlice(q), [][]any{{1, "one"}, {2, "two"}, {3, "three"}}) // Output: // [[1 one] [2 two] [3 three]] @@ -1393,13 +1395,13 @@ func TestExampleOrderedQuery_ThenByDescendingT(t *testing.T) { time.Date(2015, 7, 10, 0, 0, 0, 0, time.Local), } - orderedDates := ToSlice[string](Select[time.Time, string](func(t time.Time) string { + orderedDates := ToSlice(Select(func(t time.Time) string { return t.Format("2006-Jan-02") - })(ThenByDescending[time.Time, int](generics.NumericCompare[int], func(date time.Time) int { + })(ThenByDescending(generics.NumericCompare[int], func(date time.Time) int { return int(date.Month()) - })(OrderBy[time.Time, int](generics.NumericCompare[int], func(date time.Time) int { + })(OrderBy(generics.NumericCompare[int], func(date time.Time) int { return date.Year() - })(FromSlice[time.Time](dates))).Query)) + })(FromSlice(dates))).Query)) assert.DeepEqual(t, orderedDates, []string{ "2013-May-04", "2014-Jul-11", "2015-Jul-10", "2015-Mar-23", "2015-Jan-02", @@ -1425,13 +1427,13 @@ func TestExampleOrderedQuery_ThenByT(t *testing.T) { time.Date(2015, 7, 10, 0, 0, 0, 0, time.Local), } - orderedDates := ToSlice[string](Select[time.Time, string](func(t time.Time) string { + orderedDates := ToSlice(Select(func(t time.Time) string { return t.Format("2006-Jan-02") - })(ThenBy[time.Time, int](generics.NumericCompare[int], func(date time.Time) int { + })(ThenBy(generics.NumericCompare[int], func(date time.Time) int { return int(date.Day()) - })(OrderBy[time.Time, int](generics.NumericCompare[int], func(date time.Time) int { + })(OrderBy(generics.NumericCompare[int], func(date time.Time) int { return date.Year() - })(FromSlice[time.Time](dates))).Query)) + })(FromSlice(dates))).Query)) assert.DeepEqual(t, orderedDates, []string{ "2013-May-04", "2014-Jul-11", "2015-Jan-02", "2015-Jul-10", "2015-Mar-23", @@ -1456,9 +1458,9 @@ func TestExampleQuery_AggregateT(t *testing.T) { // Prepend each word to the beginning of the // new sentence to reverse the word order. - reversed := Aggregate[string]( + reversed := Aggregate( func(workingSentence string, next string) string { return next + " " + workingSentence }, - )(FromSlice[string](words)) + )(FromSlice(words)) assert.DeepEqual(t, reversed, "dog lazy the over jumps fox brown quick the") // Output: // dog lazy the over jumps fox brown quick the @@ -1470,14 +1472,14 @@ func TestExampleQuery_AggregateWithSeedT(t *testing.T) { fruits := []string{"apple", "mango", "orange", "passionfruit", "grape"} // Determine whether any string in the array is longer than "banana". - longestName := AggregateWithSeed[string]( + longestName := AggregateWithSeed( "banan", func(longest, next string) string { if len(next) > len(longest) { return next } return longest }, - )(FromSlice[string](fruits)) + )(FromSlice(fruits)) assert.DeepEqual(t, longestName, "passionfruit") // Output: @@ -1490,7 +1492,7 @@ func TestExampleQuery_AggregateWithSeedByT(t *testing.T) { input := []string{"apple", "mango", "orange", "passionfruit", "grape"} // Determine whether any string in the array is longer than "banana". - longestName := AggregateWithSeedBy[string]("banana", + longestName := AggregateWithSeedBy("banana", func(longest string, next string) string { if len(longest) > len(next) { return longest @@ -1501,7 +1503,7 @@ func TestExampleQuery_AggregateWithSeedByT(t *testing.T) { // Return the final result func(result string) string { return fmt.Sprintf("The fruit with the longest name is %s.", result) - })(FromSlice[string](input)) + })(FromSlice(input)) assert.DeepEqual(t, longestName, "The fruit with the longest name is passionfruit.") // Output: // The fruit with the longest name is passionfruit. @@ -1524,17 +1526,17 @@ func TestExampleQuery_AllT(t *testing.T) { {Name: "Peter", Marks: []int{67, 78, 70, 82}}, } - approvedStudents := ToSlice[string]( - Select[Student, string](func(t Student) string { + approvedStudents := ToSlice( + Select(func(t Student) string { return t.Name - })(Where[Student]( + })(Where( func(student Student) bool { - return All[int]( + return All( func(mark int) bool { return mark > 70 }, - )(FromSlice[int](student.Marks)) + )(FromSlice(student.Marks)) }, - )(FromSlice[Student](students)))) + )(FromSlice(students)))) //List of approved students assert.DeepEqual(t, approvedStudents, []string{"Hugo", "Michael"}) @@ -1560,24 +1562,24 @@ func TestExampleQuery_AnyWithT(t *testing.T) { {Name: "Peter", Marks: []int{67, 78, 70, 82}}, } - studentsWithAnyMarkLt70 := ToSlice[string]( - Select[Student, string]( + studentsWithAnyMarkLt70 := ToSlice( + Select( func(t Student) string { return t.Name }, )( - Where[Student]( + Where( func(student Student) bool { - return AnyWith[int]( + return AnyWith( func(mark int) bool { return mark < 70 }, - )(FromSlice[int]( + )(FromSlice( student.Marks, )) }, - )(FromSlice[Student](students)), + )(FromSlice(students)), ), ) @@ -1605,13 +1607,13 @@ func TestExampleQuery_CountWithT(t *testing.T) { {Name: "Whiskers", Vaccinated: false}, } - numberUnvaccinated := CountWith[Pet]( + numberUnvaccinated := CountWith( func(p Pet) bool { return p.Vaccinated == false }, - )(FromSlice[Pet](pets)) + )(FromSlice(pets)) assert.DeepEqual(t, numberUnvaccinated, 2) //Output: @@ -1634,15 +1636,15 @@ func TestExampleQuery_DistinctByT(t *testing.T) { } //Exclude duplicates. - noduplicates := ToSlice[[]any]( - Select[Product, []any]( + noduplicates := ToSlice( + Select( func(p Product) []any { return []any{p.Name, p.Code} }, )( - DistinctBy[Product](func(item Product) int { return item.Code })(FromSlice[Product](products)), + DistinctBy(func(item Product) int { return item.Code })(FromSlice(products)), ), ) @@ -1679,16 +1681,16 @@ func TestExampleQuery_ExceptByT(t *testing.T) { //Order and exclude duplicates. - expect := ToSlice[[]any]( - Select[Product, []any]( + expect := ToSlice( + Select( func(p Product) []any { return []any{p.Name, p.Code} }, )( - ExceptBy[Product, int]( + ExceptBy( func(item Product) int { return item.Code }, - )(FromSlice[Product](fruits1), FromSlice[Product](fruits2)), + )(FromSlice(fruits1), FromSlice(fruits2)), )) assert.DeepEqual(t, expect, [][]any{ {"orange", 4}, @@ -1706,9 +1708,9 @@ func TestExampleQuery_ExceptByT(t *testing.T) { func TestExampleQuery_FirstWithT(t *testing.T) { numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19} - first, _ := FirstWith[int]( + first, _ := FirstWith( func(item int) bool { return item > 80 }, - )(FromSlice[int](numbers)) + )(FromSlice(numbers)) assert.DeepEqual(t, first, 92) // Output: // 92 @@ -1719,11 +1721,11 @@ func TestExampleQuery_FirstWithT(t *testing.T) { // to output all elements of an array. func TestExampleQuery_ForEach(t *testing.T) { fruits := []string{"orange", "apple", "lemon", "apple"} - ForEach[string]( + ForEach( func(fruit string) { fmt.Println(fruit) }, - )(FromSlice[string](fruits)) + )(FromSlice(fruits)) // Output: // orange @@ -1737,11 +1739,11 @@ func TestExampleQuery_ForEach(t *testing.T) { func TestExampleQuery_ForEachIndexed(t *testing.T) { fruits := []string{"orange", "apple", "lemon", "apple"} - ForEachIndexed[string]( + ForEachIndexed( func(i int, fruit string) { fmt.Printf("%d.%s\n", i, fruit) }, - )(FromSlice[string](fruits)) + )(FromSlice(fruits)) // Output: // 0.orange // 1.apple @@ -1753,9 +1755,9 @@ func TestExampleQuery_ForEachIndexed(t *testing.T) { // to output all elements of an array. func TestExampleQuery_ForEachT(t *testing.T) { fruits := []string{"orange", "apple", "lemon", "apple"} - ForEach[string](func(fruit string) { + ForEach(func(fruit string) { fmt.Println(fruit) - })(FromSlice[string](fruits)) + })(FromSlice(fruits)) // Output: // orange // apple @@ -1768,9 +1770,9 @@ func TestExampleQuery_ForEachT(t *testing.T) { func TestExampleQuery_ForEachIndexedT(t *testing.T) { fruits := []string{"orange", "apple", "lemon", "apple"} - ForEachIndexed[string](func(i int, fruit string) { + ForEachIndexed(func(i int, fruit string) { fmt.Printf("%d.%s\n", i, fruit) - })(FromSlice[string](fruits)) + })(FromSlice(fruits)) // Output: // 0.orange // 1.apple @@ -1797,10 +1799,10 @@ func TestExampleQuery_GroupByT(t *testing.T) { // Group the pets using Age as the key value // and selecting only the pet's Name for each value. - query := ToSlice[Group[int, string]](OrderBy[Group[int, string], int](generics.NumericCompare[int], func(g Group[int, string]) int { return g.Key })(GroupBy[Pet, int, string]( + query := ToSlice(OrderBy(generics.NumericCompare[int], func(g Group[int, string]) int { return g.Key })(GroupBy( func(p Pet) int { return p.Age }, func(p Pet) string { return p.Name }, - )(FromSlice[Pet](pets))).Query) + )(FromSlice(pets))).Query) assert.DeepEqual(t, query, []Group[int, string]{ {1, []string{"Whiskers"}}, {4, []string{"Boots", "Daisy"}}, @@ -1818,7 +1820,8 @@ func TestExampleQuery_GroupByT(t *testing.T) { } // The following code example demonstrates how to use GroupJoinT -// to perform a grouped join on two slices. +// +// to perform a grouped join on two slices. func TestExampleQuery_GroupJoinT(t *testing.T) { type Person struct { @@ -1846,19 +1849,19 @@ func TestExampleQuery_GroupJoinT(t *testing.T) { // that contains a person's name as the key and a slice of strings // of names of the pets they own as a value. - q := ToSlice[KeyValue[string, []string]]( - GroupJoin[Person, Pet, KeyValue[string, []string], Person]( + q := ToSlice( + GroupJoin( func(p Person) Person { return p }, func(p Pet) Person { return p.Owner }, func(person Person, pets []Pet) KeyValue[string, []string] { - return KeyValue[string, []string]{person.Name, ToSlice[string]( - Select[Pet, string]( + return KeyValue[string, []string]{person.Name, ToSlice( + Select( func(pet Pet) string { return pet.Name }, - )(FromSlice[Pet](pets)), + )(FromSlice(pets)), )} }, - )(FromSlice[Person](people), FromSlice[Pet](pets)), + )(FromSlice(people), FromSlice(pets)), ) assert.DeepEqual(t, q, []KeyValue[string, []string]{ @@ -1909,18 +1912,18 @@ func TestExampleQuery_IntersectByT(t *testing.T) { {Name: "apple", Code: 9}, } - duplicates := ToSlice[[]any]( - Select[Product, []any]( + duplicates := ToSlice( + Select( func(p Product) []any { return []any{p.Name, p.Code} }, )( - IntersectBy[Product, int]( + IntersectBy( func(p Product) int { return p.Code }, )( - FromSlice[Product](store1), - FromSlice[Product](store2), + FromSlice(store1), + FromSlice(store2), ), ), ) @@ -1961,12 +1964,12 @@ func TestExampleQuery_JoinT(t *testing.T) { // each element is an anonymous type that contains a // Pet's name and the name of the Person that owns the Pet. - query := ToSlice[string]( - Join[Person, Pet, string, Person]( + query := ToSlice( + Join( func(person Person) Person { return person }, func(pet Pet) Person { return pet.Owner }, func(person Person, pet Pet) string { return fmt.Sprintf("%s - %s", person.Name, pet.Name) }, - )(FromSlice[Person](people), FromSlice[Pet](pets)), + )(FromSlice(people), FromSlice(pets)), ) assert.DeepEqual(t, query, []string{ @@ -1989,7 +1992,7 @@ func TestExampleQuery_LastWithT(t *testing.T) { numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 67, 12, 19} - last, _ := LastWith[int](func(n int) bool { return n > 80 })(FromSlice[int](numbers)) + last, _ := LastWith(func(n int) bool { return n > 80 })(FromSlice(numbers)) assert.DeepEqual(t, last, 87) @@ -2016,8 +2019,8 @@ func TestExampleQuery_OrderByDescendingT(t *testing.T) { //Order and get the top 3 players - top3Players := ToSlice[string]( - Select[KeyValue[int64, Player], string]( + top3Players := ToSlice( + Select( func(kv KeyValue[int64, Player]) string { return fmt.Sprintf( "Rank: #%d - Player: %s - Points: %d", @@ -2028,15 +2031,16 @@ func TestExampleQuery_OrderByDescendingT(t *testing.T) { }, )( - SelectIndexed[Player, KeyValue[int64, Player]]( + SelectIndexed( func(i int, p Player) KeyValue[int64, Player] { return KeyValue[int64, Player]{Key: int64(i + 1), Value: p} }, - )(Take[Player](3)( - OrderByDescending[Player, int64]( + )(Take( + OrderByDescending( generics.NumericCompare[int64], func(p Player) int64 { return p.Points }, - )(FromSlice[Player](players)).Query, + )(FromSlice(players)).Query, + 3, ))), ) assert.DeepEqual(t, top3Players, []string{ @@ -2066,18 +2070,18 @@ func TestExampleQuery_OrderByT(t *testing.T) { {Name: "Daisy", Age: 4}, } - orderedPets := ToSlice[string]( - Select[Pet, string]( + orderedPets := ToSlice( + Select( func(pet Pet) string { return fmt.Sprintf("%s - %d", pet.Name, pet.Age) }, )( - OrderBy[Pet, int]( + OrderBy( generics.NumericCompare[int], func(pet Pet) int { return pet.Age }, )( - FromSlice[Pet](pets), + FromSlice(pets), ).Query, ), ) @@ -2099,8 +2103,8 @@ func TestExampleQuery_OrderByT(t *testing.T) { // The following code example demonstrates how to use SelectT // to project over a slice. func TestExampleQuery_SelectT(t *testing.T) { - squares := ToSlice[int]( - Select[int, int]( + squares := ToSlice( + Select( func(x int) int { return x * x }, )(Range(1, 10)), ) @@ -2116,16 +2120,16 @@ func TestExampleQuery_SelectT(t *testing.T) { func TestExampleQuery_SelectIndexedT(t *testing.T) { numbers := []int{5, 4, 1, 3, 9, 8, 6, 7, 2, 0} - numsInPlace := ToSlice[string]( - Select[KeyValue[int, bool], string]( + numsInPlace := ToSlice( + Select( func(kv KeyValue[int, bool]) string { return fmt.Sprintf("%d: %t", kv.Key, kv.Value) }, )( - SelectIndexed[int, KeyValue[int, bool]]( + SelectIndexed( func(index, num int) KeyValue[int, bool] { return KeyValue[int, bool]{Key: num, Value: (num == index)} }, )( - FromSlice[int](numbers), + FromSlice(numbers), ), ), ) @@ -2185,14 +2189,14 @@ func TestExampleQuery_SelectManyByT(t *testing.T) { } people := []Person{magnus, terry, charlotte} - results := ToSlice[string]( - SelectManyBy[Person, Pet, string]( - func(person Person) Query[Pet] { return FromSlice[Pet](person.Pets) }, + results := ToSlice( + SelectManyBy( + func(person Person) Query[Pet] { return FromSlice(person.Pets) }, func(pet Pet, person Person) string { return fmt.Sprintf("Owner: %s, Pet: %s", person.Name, pet.Name) }, )( - FromSlice[Person](people), + FromSlice(people), )) assert.DeepEqual(t, results, []string{ @@ -2223,27 +2227,27 @@ func TestExampleQuery_SelectManyT(t *testing.T) { "The wizard quickly jinxed the gnomes before they vaporized", } - results := ToSlice[string]( - SelectIndexed[Group[string, string], string]( + results := ToSlice( + SelectIndexed( func(index int, wordGroup Group[string, string]) string { return fmt.Sprintf("Rank: #%d, Word: %s, Counts: %d", index+1, wordGroup.Key, len(wordGroup.Group)) })( - Take[Group[string, string]](5)(ThenBy[Group[string, string], string]( + Take(ThenBy( strings.Compare, func(wordGroup Group[string, string]) string { return wordGroup.Key - })(OrderByDescending[Group[string, string], int]( + })(OrderByDescending( generics.NumericCompare[int], func(wordGroup Group[string, string]) int { return len(wordGroup.Group) - })(GroupBy[string, string, string]( + })(GroupBy( func(word string) string { return word }, func(word string) string { return word }, )( - SelectMany[string, string]( + SelectMany( func(sentence string) Query[string] { - return FromSlice[string](strings.Split(sentence, " ")) - })(FromSlice[string](sentences))))).Query), + return FromSlice(strings.Split(sentence, " ")) + })(FromSlice(sentences))))).Query, 5), ), ) @@ -2296,12 +2300,12 @@ func TestExampleQuery_SelectManyIndexedT(t *testing.T) { } logFiles := []LogFile{file1, file2, file3} - results := ToSlice[string](SelectManyIndexed[LogFile, string]( + results := ToSlice(SelectManyIndexed( func(fileIndex int, file LogFile) Query[string] { - return SelectIndexed[string, string](func(lineIndex int, line string) string { + return SelectIndexed(func(lineIndex int, line string) string { return fmt.Sprintf("File:[%d] - %s => line: %d - %s", fileIndex+1, file.Name, lineIndex+1, line) - })(FromSlice[string](file.Lines)) - })(FromSlice[LogFile](logFiles))) + })(FromSlice(file.Lines)) + })(FromSlice(logFiles))) assert.DeepEqual(t, results, []string{ "File:[1] - file1.log => line: 1 - INFO: 2013/11/05 18:11:01 main.go:44: Special Information", @@ -2348,20 +2352,20 @@ func TestExampleQuery_SelectManyByIndexedT(t *testing.T) { people := []Person{magnus, terry, charlotte} - results := ToSlice[string]( - SelectManyByIndexed[Person, string, string]( + results := ToSlice( + SelectManyByIndexed( func(index int, person Person) Query[string] { - return Select[Pet, string]( + return Select( func(pet Pet) string { return fmt.Sprintf("%d - %s", index, pet.Name) }, - )(FromSlice[Pet](person.Pets)) + )(FromSlice(person.Pets)) }, func(indexedPet string, person Person) string { return fmt.Sprintf("Pet: %s, Owner: %s", indexedPet, person.Name) }, - )(FromSlice[Person](people)), + )(FromSlice(people)), ) assert.DeepEqual(t, results, []string{ "Pet: 0 - Daisy, Owner: Hedlund, Magnus", @@ -2378,13 +2382,13 @@ func TestExampleQuery_SelectManyByIndexedT(t *testing.T) { } -//The following code example demonstrates how to use SingleWithT +// The following code example demonstrates how to use SingleWithT // to select the only element of a slice that satisfies a condition. func TestExampleQuery_SingleWithT(t *testing.T) { fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"} - fruit, _ := SingleWith[string]( + fruit, _ := SingleWith( func(f string) bool { return len(f) > 10 }, - )(FromSlice[string](fruits)) + )(FromSlice(fruits)) assert.DeepEqual(t, fruit, "passionfruit") // Output: // passionfruit @@ -2394,10 +2398,10 @@ func TestExampleQuery_SingleWithT(t *testing.T) { // to skip elements of an array as long as a condition is true. func TestExampleQuery_SkipWhileT(t *testing.T) { grades := []int{59, 82, 70, 56, 92, 98, 85} - lowerGrades := ToSlice[int]( - SkipWhile[int]( + lowerGrades := ToSlice( + SkipWhile( func(g int) bool { return g >= 80 })( - OrderByDescending[int, int](generics.NumericCompare[int], func(g int) int { return g })(FromSlice[int](grades)).Query), + OrderByDescending(generics.NumericCompare[int], func(g int) int { return g })(FromSlice(grades)).Query), ) //"All grades below 80: @@ -2412,9 +2416,9 @@ func TestExampleQuery_SkipWhileT(t *testing.T) { func TestExampleQuery_SkipWhileIndexedT(t *testing.T) { amounts := []int{5000, 2500, 9000, 8000, 6500, 4000, 1500, 5500} - query := ToSlice[int]( - SkipWhileIndexed[int](func(index int, amount int) bool { return amount > index*1000 })( - FromSlice[int](amounts), + query := ToSlice( + SkipWhileIndexed(func(index int, amount int) bool { return amount > index*1000 })( + FromSlice(amounts), ), ) assert.DeepEqual(t, query, []int{4000, 1500, 5500}) @@ -2438,13 +2442,13 @@ func TestExampleQuery_SortT(t *testing.T) { {Name: "Daisy", Age: 4}, } - orderedPets := ToSlice[string]( - Select[Pet, string]( + orderedPets := ToSlice( + Select( func(pet Pet) string { return fmt.Sprintf("%s - %d", pet.Name, pet.Age) }, )( - Sort[Pet](func(pet1 Pet, pet2 Pet) bool { return pet1.Age < pet2.Age })(FromSlice[Pet](pets)), + Sort(func(pet1 Pet, pet2 Pet) bool { return pet1.Age < pet2.Age })(FromSlice(pets)), ), ) @@ -2467,10 +2471,10 @@ func TestExampleQuery_SortT(t *testing.T) { func TestExampleQuery_TakeWhileT(t *testing.T) { fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"} - query := ToSlice[string]( - TakeWhile[string]( + query := ToSlice( + TakeWhile( func(fruit string) bool { return fruit != "orange" }, - )(FromSlice[string](fruits)), + )(FromSlice(fruits)), ) assert.DeepEqual(t, query, []string{"apple", "banana", "mango"}) // Output: @@ -2485,10 +2489,10 @@ func TestExampleQuery_TakeWhileIndexedT(t *testing.T) { fruits := []string{"apple", "passionfruit", "banana", "mango", "orange", "blueberry", "grape", "strawberry"} - query := ToSlice[string]( - TakeWhileIndexed[string]( + query := ToSlice( + TakeWhileIndexed( func(index int, fruit string) bool { return len(fruit) >= index }, - )(FromSlice[string](fruits)), + )(FromSlice(fruits)), ) assert.DeepEqual(t, query, []string{"apple", "passionfruit", "banana", "mango", "orange", "blueberry"}) // Output: @@ -2510,10 +2514,10 @@ func TestExampleQuery_ToMapByT(t *testing.T) { {Name: "apple", Code: 9}, } - map1 := ToMapBy[int, string, Product]( + map1 := ToMapBy( func(item Product) int { return item.Code }, func(item Product) string { return item.Name }, - )(FromSlice[Product](products)) + )(FromSlice(products)) assert.DeepEqual(t, map1, map[int]string{ 4: "orange", 9: "apple", @@ -2531,9 +2535,9 @@ func TestExampleQuery_ToMapByT(t *testing.T) { func TestExampleQuery_WhereT(t *testing.T) { fruits := []string{"apple", "passionfruit", "banana", "mango", "orange", "blueberry", "grape", "strawberry"} - query := ToSlice[string](Where[string](func(f string) bool { + query := ToSlice(Where(func(f string) bool { return len(f) > 6 - })(FromSlice[string](fruits))) + })(FromSlice(fruits))) assert.DeepEqual(t, []string{"passionfruit", "blueberry", "strawberry"}, query) // Output: @@ -2545,7 +2549,7 @@ func TestExampleQuery_WhereT(t *testing.T) { func TestExampleQuery_WhereIndexedT(t *testing.T) { numbers := []int{0, 30, 20, 15, 90, 85, 40, 75} - query := ToSlice[int](WhereIndexed[int](func(index int, number int) bool { return number <= index*10 })(FromSlice[int](numbers))) + query := ToSlice(WhereIndexed(func(index int, number int) bool { return number <= index*10 })(FromSlice(numbers))) assert.DeepEqual(t, []int{0, 20, 15, 40}, query) // Output: @@ -2558,11 +2562,11 @@ func TestExampleQuery_ZipT(t *testing.T) { number := []int{1, 2, 3, 4, 5} words := []string{"one", "two", "three"} - s := Results[[]any](Zip[int, string, []any]( + s := Results(Zip( func(a int, b string) []any { return []any{a, b} }, )( - FromSlice[int](number), - FromSlice[string](words), + FromSlice(number), + FromSlice(words), )) assert.DeepEqual(t, s, [][]any{ {1, "one"}, @@ -2582,9 +2586,9 @@ func TestExampleFromChannelT(t *testing.T) { ch <- "three" close(ch) - q := FromChannel[string](ch) + q := FromChannel(ch) - assert.DeepEqual(t, Results[string](q), []string{"one", "two", "three"}) + assert.DeepEqual(t, Results(q), []string{"one", "two", "three"}) // Output: // [one two three] } diff --git a/except_test.go b/except_test.go index d1f8837..f2c243a 100644 --- a/except_test.go +++ b/except_test.go @@ -7,8 +7,8 @@ func TestExcept(t *testing.T) { input2 := []int{1, 2} want := []int{3, 4, 5, 5} - if q := Except[int](FromSlice[int](input1), FromSlice[int](input2)); !validateQuery(q, want) { - t.Errorf("From(%v).Except(%v)=%v expected %v", input1, input2, toSlice(q), want) + if q := Except(FromSlice(input1), FromSlice(input2)); !ValidateQuery(q, want) { + t.Errorf("From(%v).Except(%v)=%v expected %v", input1, input2, ToSlice(q), want) } } @@ -17,9 +17,9 @@ func TestExceptBy(t *testing.T) { input2 := []int{1} want := []int{2, 4, 2} - if q := ExceptBy[int, int](func(i int) int { + if q := ExceptBy(func(i int) int { return i % 2 - })(FromSlice[int](input1), FromSlice[int](input2)); !validateQuery(q, want) { - t.Errorf("From(%v).ExceptBy(%v)=%v expected %v", input1, input2, toSlice(q), want) + })(FromSlice(input1), FromSlice(input2)); !ValidateQuery(q, want) { + t.Errorf("From(%v).ExceptBy(%v)=%v expected %v", input1, input2, ToSlice(q), want) } } diff --git a/from_test.go b/from_test.go index 6c90e3b..623c536 100644 --- a/from_test.go +++ b/from_test.go @@ -1,8 +1,9 @@ package flinx import ( - "gotest.tools/v3/assert" "testing" + + "gotest.tools/v3/assert" ) func TestFrom(t *testing.T) { @@ -19,9 +20,9 @@ func TestFrom(t *testing.T) { {[]int{1, 2, 4}, []int{1, 2, 3}, false}, } for _, test := range tests { - if q := FromSlice[int](test.input); validateQuery(q, test.output) != test.want { + if q := FromSlice(test.input); ValidateQuery(q, test.output) != test.want { if test.want { - t.Errorf("From(%v)=%v expected %v", test.input, toSlice(q), test.output) + t.Errorf("From(%v)=%v expected %v", test.input, ToSlice(q), test.output) } else { t.Errorf("From(%v)=%v expected not equal", test.input, test.output) } @@ -40,9 +41,9 @@ func TestFrom(t *testing.T) { {"str", []rune{'s', 't', 'g'}, false}, } for _, test := range tests { - if q := FromString(test.input); validateQuery(q, test.output) != test.want { + if q := FromString(test.input); ValidateQuery(q, test.output) != test.want { if test.want { - t.Errorf("From(%v)=%v expected %v", test.input, toSlice(q), test.output) + t.Errorf("From(%v)=%v expected %v", test.input, ToSlice(q), test.output) } else { t.Errorf("From(%v)=%v expected not equal", test.input, test.output) } @@ -61,9 +62,9 @@ func TestFrom(t *testing.T) { {map[string]bool{"foo": true}, []KeyValue[string, bool]{{"foo", false}}, false}, } for _, test := range tests { - if q := FromMap[string, bool](test.input); validateQuery(q, test.output) != test.want { + if q := FromMap(test.input); ValidateQuery(q, test.output) != test.want { if test.want { - t.Errorf("From(%v)=%v expected %v", test.input, toSlice(q), test.output) + t.Errorf("From(%v)=%v expected %v", test.input, ToSlice(q), test.output) } else { t.Errorf("From(%v)=%v expected not equal", test.input, test.output) } @@ -94,9 +95,9 @@ func TestFrom(t *testing.T) { } for _, test := range tests { - if q := FromChannel[int](test.input); validateQuery(q, test.output) != test.want { + if q := FromChannel(test.input); ValidateQuery(q, test.output) != test.want { if test.want { - t.Errorf("From(%v)=%v expected %v", test.input, toSlice(q), test.output) + t.Errorf("From(%v)=%v expected %v", test.input, ToSlice(q), test.output) } else { t.Errorf("From(%v)=%v expected not equal", test.input, test.output) } @@ -137,7 +138,7 @@ func TestFrom(t *testing.T) { } } for _, test := range tests { - res := Results[any](FromIterable[any](fooIterator())) + res := Results(FromIterable(fooIterator())) assert.DeepEqual(t, res, test.output) } @@ -154,7 +155,7 @@ func TestFromChannel(t *testing.T) { w := []int{10, 15, -3} - if q := FromChannel[int](c); !validateQuery(q, w) { + if q := FromChannel(c); !ValidateQuery(q, w) { t.Errorf("FromChannel() failed expected %v", w) } } @@ -168,7 +169,7 @@ func TestFromChannelT(t *testing.T) { w := []int{10, 15, -3} - if q := FromChannel[int](c); !validateQuery(q, w) { + if q := FromChannel(c); !ValidateQuery(q, w) { t.Errorf("FromChannelT() failed expected %v", w) } } @@ -177,7 +178,7 @@ func TestFromString(t *testing.T) { s := "string" w := []rune{'s', 't', 'r', 'i', 'n', 'g'} - if q := FromString(s); !validateQuery(q, w) { + if q := FromString(s); !ValidateQuery(q, w) { t.Errorf("FromString(%v)!=%v", s, w) } } @@ -208,7 +209,7 @@ func TestFromIterable(t *testing.T) { return } } - res := Results[any](FromIterable[any](fooIterator())) + res := Results(FromIterable(fooIterator())) assert.DeepEqual(t, res, w) } @@ -216,15 +217,15 @@ func TestFromIterable(t *testing.T) { func TestRange(t *testing.T) { w := []int{-2, -1, 0, 1, 2} - if q := Range(-2, 5); !validateQuery(q, w) { - t.Errorf("Range(-2, 5)=%v expected %v", toSlice(q), w) + if q := Range(-2, 5); !ValidateQuery(q, w) { + t.Errorf("Range(-2, 5)=%v expected %v", ToSlice(q), w) } } func TestRepeat(t *testing.T) { w := []int{1, 1, 1, 1, 1} - if q := Repeat(1, 5); !validateQuery(q, w) { - t.Errorf("Repeat(1, 5)=%v expected %v", toSlice(q), w) + if q := Repeat(1, 5); !ValidateQuery(q, w) { + t.Errorf("Repeat(1, 5)=%v expected %v", ToSlice(q), w) } } diff --git a/go.mod b/go.mod index e7edd03..a33a743 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,10 @@ module github.com/kom0055/go-flinx -go 1.18 +go 1.19 require ( github.com/ahmetb/go-linq/v3 v3.2.0 - github.com/google/go-cmp v0.5.8 - golang.org/x/exp v0.0.0-20220706164943-b4a6d9510983 + github.com/google/go-cmp v0.5.9 + golang.org/x/exp v0.0.0-20221011201855-a3968a42eed6 gotest.tools/v3 v3.3.0 ) diff --git a/go.sum b/go.sum index 8007791..593606d 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,15 @@ github.com/ahmetb/go-linq/v3 v3.2.0 h1:BEuMfp+b59io8g5wYzNoFe9pWPalRklhlhbiU3hYZDE= github.com/ahmetb/go-linq/v3 v3.2.0/go.mod h1:haQ3JfOeWK8HpVxMtHHEMPVgBKiYyQ+f1/kLZh/cj9U= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20220706164943-b4a6d9510983 h1:sUweFwmLOje8KNfXAVqGGAsmgJ/F8jJ6wBLJDt4BTKY= -golang.org/x/exp v0.0.0-20220706164943-b4a6d9510983/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20221011201855-a3968a42eed6 h1:+hSdOdB7nHAFs+EDQXTvkJj7kUMugNAcE2x+BwxlVt4= +golang.org/x/exp v0.0.0-20221011201855-a3968a42eed6/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/groupby_test.go b/groupby_test.go index 3f6a2b6..5ea1921 100644 --- a/groupby_test.go +++ b/groupby_test.go @@ -10,14 +10,14 @@ func TestGroupBy(t *testing.T) { wantEven := []int{2, 4, 6, 8} wantOdd := []int{1, 3, 5, 7, 9} - q := GroupBy[int, int, int]( + q := GroupBy( func(t int) int { return t % 2 }, func(t int) int { return t }, - )(FromSlice[int](input)) + )(FromSlice(input)) next := q.Iterate() eq := true @@ -38,6 +38,6 @@ func TestGroupBy(t *testing.T) { } if !eq { - t.Errorf("From(%v).GroupBy()=%v", input, toSlice(q)) + t.Errorf("From(%v).GroupBy()=%v", input, ToSlice(q)) } } diff --git a/groupjoin_test.go b/groupjoin_test.go index b180bc4..2567293 100644 --- a/groupjoin_test.go +++ b/groupjoin_test.go @@ -11,7 +11,7 @@ func TestGroupJoin(t *testing.T) { {2, 0}, } - q := GroupJoin[int, int, KeyValue[int, int], int]( + q := GroupJoin( func(t int) int { return t }, @@ -23,9 +23,9 @@ func TestGroupJoin(t *testing.T) { outer, len(inners), } }, - )(FromSlice[int](outer), FromSlice[int](inner)) + )(FromSlice(outer), FromSlice(inner)) - if !validateQuery(q, want) { - t.Errorf("From().GroupJoin()=%v expected %v", toSlice(q), want) + if !ValidateQuery(q, want) { + t.Errorf("From().GroupJoin()=%v expected %v", ToSlice(q), want) } } diff --git a/index_test.go b/index_test.go index 89745ec..d798e9b 100644 --- a/index_test.go +++ b/index_test.go @@ -23,7 +23,7 @@ func TestIndexOf(t *testing.T) { for _, test := range tests { - index := IndexOf[int](test.predicate)(FromSlice[int](test.input)) + index := IndexOf(test.predicate)(FromSlice(test.input)) if index != test.expected { t.Errorf("From(%v).IndexOf() expected %v received %v", test.input, test.expected, index) } @@ -56,7 +56,7 @@ func TestIndexOf(t *testing.T) { } for _, test := range tests { - index := IndexOf[rune](test.predicate)(FromString(test.input)) + index := IndexOf(test.predicate)(FromString(test.input)) if index != test.expected { t.Errorf("From(%v).IndexOf() expected %v received %v", test.input, test.expected, index) } diff --git a/intersect_test.go b/intersect_test.go index ce4f9f0..536c48d 100644 --- a/intersect_test.go +++ b/intersect_test.go @@ -7,8 +7,8 @@ func TestIntersect(t *testing.T) { input2 := []int{1, 4, 7, 9, 12, 3} want := []int{1, 3} - if q := Intersect[int](FromSlice[int](input1), FromSlice[int](input2)); !validateQuery(q, want) { - t.Errorf("From(%v).Intersect(%v)=%v expected %v", input1, input2, toSlice(q), want) + if q := Intersect(FromSlice(input1), FromSlice(input2)); !ValidateQuery(q, want) { + t.Errorf("From(%v).Intersect(%v)=%v expected %v", input1, input2, ToSlice(q), want) } } @@ -17,9 +17,9 @@ func TestIntersectBy(t *testing.T) { input2 := []int{1, 4, 7, 9, 12, 3} want := []int{5, 8} - if q := IntersectBy[int, int](func(i int) int { + if q := IntersectBy(func(i int) int { return i % 2 - })(FromSlice[int](input1), FromSlice[int](input2)); !validateQuery(q, want) { - t.Errorf("From(%v).IntersectBy(%v)=%v expected %v", input1, input2, toSlice(q), want) + })(FromSlice(input1), FromSlice(input2)); !ValidateQuery(q, want) { + t.Errorf("From(%v).IntersectBy(%v)=%v expected %v", input1, input2, ToSlice(q), want) } } diff --git a/join_test.go b/join_test.go index cd0ed48..48ec393 100644 --- a/join_test.go +++ b/join_test.go @@ -13,13 +13,13 @@ func TestJoin(t *testing.T) { {4, 4}, } - q := Join[int, int, KeyValue[int, int], int](func(i int) int { return i }, + q := Join(func(i int) int { return i }, func(i int) int { return i }, func(outer int, inner int) KeyValue[int, int] { return KeyValue[int, int]{outer, inner} }, - )(FromSlice[int](outer), FromSlice[int](inner)) - if !validateQuery[KeyValue[int, int]](q, want) { - t.Errorf("From().Join()=%v expected %v", toSlice(q), want) + )(FromSlice(outer), FromSlice(inner)) + if !ValidateQuery(q, want) { + t.Errorf("From().Join()=%v expected %v", ToSlice(q), want) } } diff --git a/orderby_test.go b/orderby_test.go index a968b6d..badee37 100644 --- a/orderby_test.go +++ b/orderby_test.go @@ -1,14 +1,15 @@ package flinx import ( - "github.com/kom0055/go-flinx/generics" "testing" + + "github.com/kom0055/go-flinx/generics" ) func TestEmpty(t *testing.T) { - q := OrderBy[string, int](generics.NumericCompare[int], func(in string) int { + q := OrderBy(generics.NumericCompare[int], func(in string) int { return 0 - })(FromSlice[string]([]string{})) + })(FromSlice([]string{})) _, ok := q.Iterate()() if ok { @@ -23,7 +24,7 @@ func TestOrderBy(t *testing.T) { slice[i].f1 = i } - q := OrderBy[foo, int](generics.NumericCompare[int], getF1)(FromSlice[foo](slice)) + q := OrderBy(generics.NumericCompare[int], getF1)(FromSlice(slice)) j := 0 next := q.Iterate() @@ -43,8 +44,8 @@ func TestOrderByDescending(t *testing.T) { slice[i].f1 = i } - q := OrderByDescending[foo, int](generics.NumericCompare[int], - getF1)(FromSlice[foo](slice)) + q := OrderByDescending(generics.NumericCompare[int], + getF1)(FromSlice(slice)) j := len(slice) - 1 next := q.Iterate() @@ -65,8 +66,8 @@ func TestThenBy(t *testing.T) { slice[i].f2 = i%2 == 0 } - q := ThenBy[foo, int](generics.OrderedCompare[int], getF1)( - OrderBy[foo, bool](generics.BoolCompare, getF2)(FromSlice[foo](slice)), + q := ThenBy(generics.OrderedCompare[int], getF1)( + OrderBy(generics.BoolCompare, getF2)(FromSlice(slice)), ) next := q.Iterate() @@ -85,8 +86,8 @@ func TestThenByDescending(t *testing.T) { slice[i].f2 = i%2 == 0 } - orderByFn := OrderBy[foo, bool](generics.BoolCompare, getF2)(FromSlice[foo](slice)) - thenByDescFn := ThenByDescending[foo, int](generics.NumericCompare[int], getF1)(orderByFn) + orderByFn := OrderBy(generics.BoolCompare, getF2)(FromSlice(slice)) + thenByDescFn := ThenByDescending(generics.NumericCompare[int], getF1)(orderByFn) q := thenByDescFn next := q.Iterate() @@ -104,9 +105,9 @@ func TestSort(t *testing.T) { slice[i].f1 = i } - q := Sort[foo](func(i, j foo) bool { + q := Sort(func(i, j foo) bool { return i.f1 < j.f1 - })(FromSlice[foo](slice)) + })(FromSlice(slice)) j := 0 next := q.Iterate() diff --git a/result.go b/result.go index b429b0a..833003a 100644 --- a/result.go +++ b/result.go @@ -1,9 +1,10 @@ package flinx import ( + "math" + "golang.org/x/exp/constraints" _ "golang.org/x/exp/constraints" - "math" ) // All determines whether all elements of a collection satisfy a condition. @@ -314,17 +315,15 @@ func SingleWith[T any](predicate func(T) bool) func(q Query[T]) (r T, found bool // // Values can be of any integer type: int, int8, int16, int32, int64. The result // is int64. Method returns zero if collection contains no elements. -func Sum[T, V constraints.Integer | constraints.Float](q Query[T]) (r V) { +func Sum[T constraints.Integer | constraints.Float](q Query[T]) (r T) { next := q.Iterate() item, ok := next() if !ok { return 0 } - - r = V(item) - + r = item for item, ok = next(); ok; item, ok = next() { - r += V(item) + r += item } return diff --git a/result_test.go b/result_test.go index 0aa8344..d5598f0 100644 --- a/result_test.go +++ b/result_test.go @@ -1,23 +1,24 @@ package flinx import ( - "github.com/kom0055/go-flinx/generics" - "gotest.tools/v3/assert" "math" "reflect" "testing" + + "github.com/kom0055/go-flinx/generics" + "gotest.tools/v3/assert" ) func TestAll(t *testing.T) { input := []int{2, 4, 6, 8} - r1 := All[int](func(i int) bool { + r1 := All(func(i int) bool { return i%2 == 0 - })(FromSlice[int](input)) - r2 := All[int](func(i int) bool { + })(FromSlice(input)) + r2 := All(func(i int) bool { return i%2 != 0 - })(FromSlice[int](input)) + })(FromSlice(input)) if !r1 { t.Errorf("From(%v).All()=%v", input, r1) } @@ -41,7 +42,7 @@ func TestAny(t *testing.T) { for _, test := range tests { - if r := Any[int](FromSlice[int](test.input)); r != test.want { + if r := Any(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).Any()=%v expected %v", test.input, r, test.want) } } @@ -56,7 +57,7 @@ func TestAny(t *testing.T) { } for _, test := range tests { - if r := Any[rune](FromString(test.input)); r != test.want { + if r := Any(FromString(test.input)); r != test.want { t.Errorf("From(%v).Any()=%v expected %v", test.input, r, test.want) } } @@ -75,9 +76,9 @@ func TestAnyWith(t *testing.T) { for _, test := range tests { - if r := AnyWith[int](func(i int) bool { + if r := AnyWith(func(i int) bool { return i == 4 - })(FromSlice[int](test.input)); r != test.want { + })(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).Any()=%v expected %v", test.input, r, test.want) } } @@ -93,7 +94,7 @@ func TestAverage(t *testing.T) { } for _, test := range tests { - if r := Average[int](FromSlice[int](test.input)); r != test.want { + if r := Average(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).Average()=%v expected %v", test.input, r, test.want) } } @@ -108,7 +109,7 @@ func TestAverage(t *testing.T) { } for _, test := range tests { - if r := Average[uint](FromSlice[uint](test.input)); r != test.want { + if r := Average(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).Average()=%v expected %v", test.input, r, test.want) } } @@ -122,7 +123,7 @@ func TestAverage(t *testing.T) { } for _, test := range tests { - if r := Average[float32](FromSlice[float32](test.input)); r != test.want { + if r := Average(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).Average()=%v expected %v", test.input, r, test.want) } } @@ -131,7 +132,7 @@ func TestAverage(t *testing.T) { func TestAverageForNaN(t *testing.T) { - if r := Average[int](FromSlice[int]([]int{})); !math.IsNaN(r) { + if r := Average(FromSlice([]int{})); !math.IsNaN(r) { t.Errorf("From([]int{}).Average()=%v expected %v", r, math.NaN()) } } @@ -147,7 +148,7 @@ func TestContains(t *testing.T) { } for _, test := range tests { - if r := Contains[int](test.value)(FromSlice[int](test.input)); r != test.want { + if r := Contains(test.value)(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).Contains(%v)=%v expected %v", test.input, test.value, r, test.want) } } @@ -162,7 +163,7 @@ func TestContains(t *testing.T) { } for _, test := range tests { - if r := Contains[uint](test.value)(FromSlice[uint](test.input)); r != test.want { + if r := Contains(test.value)(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).Contains(%v)=%v expected %v", test.input, test.value, r, test.want) } } @@ -178,7 +179,7 @@ func TestContains(t *testing.T) { } for _, test := range tests { - if r := Contains[float32](test.value)(FromSlice[float32](test.input)); r != test.want { + if r := Contains(test.value)(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).Contains(%v)=%v expected %v", test.input, test.value, r, test.want) } } @@ -196,7 +197,7 @@ func TestCount(t *testing.T) { for _, test := range tests { - if r := Count[int](FromSlice[int](test.input)); r != test.want { + if r := Count(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).Count()=%v expected %v", test.input, r, test.want) } } @@ -211,7 +212,7 @@ func TestCount(t *testing.T) { for _, test := range tests { - if r := Count[uint](FromSlice[uint](test.input)); r != test.want { + if r := Count(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).Count()=%v expected %v", test.input, r, test.want) } } @@ -226,7 +227,7 @@ func TestCount(t *testing.T) { for _, test := range tests { - if r := Count[float32](FromSlice[float32](test.input)); r != test.want { + if r := Count(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).Count()=%v expected %v", test.input, r, test.want) } } @@ -244,9 +245,9 @@ func TestCountWith(t *testing.T) { for _, test := range tests { - if r := CountWith[int](func(i int) bool { + if r := CountWith(func(i int) bool { return i <= 2 - })(FromSlice[int](test.input)); r != test.want { + })(FromSlice(test.input)); r != test.want { t.Errorf("From(%v).CountWith()=%v expected %v", test.input, r, test.want) } } @@ -262,7 +263,7 @@ func TestFirst(t *testing.T) { } for _, test := range tests { - if r, ok := First[int](FromSlice[int](test.input)); r != test.want[0] || ok != test.want[1] { + if r, ok := First(FromSlice(test.input)); r != test.want[0] || ok != test.want[1] { t.Errorf("From(%v).First()=%v %v expected %v", test.input, r, ok, test.want) } } @@ -279,9 +280,9 @@ func TestFirstWith(t *testing.T) { for _, test := range tests { - if r, ok := FirstWith[int](func(i int) bool { + if r, ok := FirstWith(func(i int) bool { return i > 2 - })(FromSlice[int](test.input)); r != test.want[0] || ok != test.want[1] { + })(FromSlice(test.input)); r != test.want[0] || ok != test.want[1] { t.Errorf("From(%v).FirstWith()=%v expected %v", test.input, r, test.want) } } @@ -299,9 +300,9 @@ func TestForEach(t *testing.T) { for _, test := range tests { output := []int{} - ForEach[int](func(i int) { + ForEach(func(i int) { output = append(output, i*2) - })(FromSlice[int](test.input)) + })(FromSlice(test.input)) if !reflect.DeepEqual(output, test.want) { t.Fatalf("From(%#v).ForEach()=%#v expected=%#v", test.input, output, test.want) @@ -321,9 +322,9 @@ func TestForEachIndexed(t *testing.T) { for _, test := range tests { output := []int{} - ForEachIndexed[int](func(index, item int) { + ForEachIndexed(func(index, item int) { output = append(output, item+index) - })(FromSlice[int](test.input)) + })(FromSlice(test.input)) if !reflect.DeepEqual(output, test.want) { t.Fatalf("From(%#v).ForEachIndexed()=%#v expected=%#v", test.input, output, test.want) @@ -341,7 +342,7 @@ func TestLast(t *testing.T) { } for _, test := range tests { - if r, ok := Last[int](FromSlice[int](test.input)); r != test.want[0] || ok != test.want[1] { + if r, ok := Last(FromSlice(test.input)); r != test.want[0] || ok != test.want[1] { t.Errorf("From(%v).Last()=%v expected %v", test.input, r, test.want) } } @@ -358,9 +359,9 @@ func TestLastWith(t *testing.T) { for _, test := range tests { - if r, ok := LastWith[int](func(i int) bool { + if r, ok := LastWith(func(i int) bool { return i > 2 - })(FromSlice[int](test.input)); r != test.want[0] || ok != test.want[1] { + })(FromSlice(test.input)); r != test.want[0] || ok != test.want[1] { t.Errorf("From(%v).LastWith()=%v expected %v", test.input, r, test.want) } } @@ -377,7 +378,7 @@ func TestMax(t *testing.T) { } for _, test := range tests { - if r, ok := Max[int](generics.NumericCompare[int])(FromSlice[int](test.input)); r != test.want[0] || ok != test.want[1] { + if r, ok := Max(generics.NumericCompare[int])(FromSlice(test.input)); r != test.want[0] || ok != test.want[1] { t.Errorf("From(%v).Max()=%v %v expected %v", test.input, r, ok, test.want) } } @@ -394,7 +395,7 @@ func TestMin(t *testing.T) { } for _, test := range tests { - if r, ok := Min[int](generics.NumericCompare[int])(FromSlice[int](test.input)); r != test.want[0] || ok != test.want[1] { + if r, ok := Min(generics.NumericCompare[int])(FromSlice(test.input)); r != test.want[0] || ok != test.want[1] { t.Errorf("From(%v).Min()=%v expected %v", test.input, r, test.want) } } @@ -404,7 +405,7 @@ func TestResults(t *testing.T) { input := []int{1, 2, 3} want := []int{1, 2, 3} - if r := Results[int](FromSlice[int](input)); !reflect.DeepEqual(r, want) { + if r := Results(FromSlice(input)); !reflect.DeepEqual(r, want) { t.Errorf("From(%v).Raw()=%v expected %v", input, r, want) } } @@ -422,7 +423,7 @@ func TestSequenceEqual(t *testing.T) { for _, test := range tests { - if r := SequenceEqual[int](FromSlice[int](test.input), FromSlice[int](test.input2)); r != test.want { + if r := SequenceEqual(FromSlice(test.input), FromSlice(test.input2)); r != test.want { t.Errorf("From(%v).SequenceEqual(%v)=%v expected %v", test.input, test.input2, r, test.want) } } @@ -439,7 +440,7 @@ func TestSingle(t *testing.T) { } for _, test := range tests { - if r, ok := Single[int](FromSlice[int](test.input)); r != test.want[0] || ok != test.want[1] { + if r, ok := Single(FromSlice(test.input)); r != test.want[0] || ok != test.want[1] { t.Errorf("From(%v).Single()=%v expected %v", test.input, r, test.want) } } @@ -457,9 +458,9 @@ func TestSingleWith(t *testing.T) { } for _, test := range tests { - if r, ok := SingleWith[int](func(i int) bool { + if r, ok := SingleWith(func(i int) bool { return i > 2 - })(FromSlice[int](test.input)); r != test.want[0] || ok != test.want[1] { + })(FromSlice(test.input)); r != test.want[0] || ok != test.want[1] { t.Errorf("From(%v).SingleWith()=%v expected %v", test.input, r, test.want) } } @@ -476,7 +477,7 @@ func TestSumInts(t *testing.T) { } for _, test := range tests { - if r := Sum[int, int64](FromSlice[int](test.input)); r != test.want { + if r := int64(Sum(FromSlice(test.input))); r != test.want { t.Errorf("From(%v).SumInts()=%v expected %v", test.input, r, test.want) } } @@ -493,7 +494,7 @@ func TestSumUInts(t *testing.T) { } for _, test := range tests { - if r := Sum[uint, uint64](FromSlice[uint](test.input)); r != test.want { + if r := Sum(FromSlice(test.input)); uint64(r) != test.want { t.Errorf("From(%v).SumInts()=%v expected %v", test.input, r, test.want) } } @@ -510,7 +511,7 @@ func TestSumFloats(t *testing.T) { } for _, test := range tests { - if r := Sum[float32, float64](FromSlice[float32](test.input)); r != test.want { + if r := Sum(FromSlice(test.input)); float64(r) != test.want { t.Errorf("From(%v).SumFloats()=%v expected %v", test.input, r, test.want) } } @@ -522,7 +523,7 @@ func TestToChannel(t *testing.T) { go func() { - ToChannel[int](FromSlice[int](input), c) + ToChannel(FromSlice(input), c) }() result := []int{} @@ -539,7 +540,7 @@ func TestToChannelT(t *testing.T) { c := make(chan string) input := []string{"1", "2", "3", "4", "5"} - go ToChannel[string](FromSlice[string](input), c) + go ToChannel(FromSlice(input), c) result := []string{} for value := range c { @@ -557,7 +558,7 @@ func TestToMap(t *testing.T) { input[2] = false input[3] = true - result := ToMap[int, bool](FromMap[int, bool](input)) + result := ToMap(FromMap(input)) if !reflect.DeepEqual(result, input) { t.Errorf("From(%v).ToMap()=%v expected %v", input, result, input) @@ -570,14 +571,14 @@ func TestToMapBy(t *testing.T) { input[2] = false input[3] = true - result := ToMapBy[int, bool, KeyValue[int, bool]]( + result := ToMapBy( func(t KeyValue[int, bool]) int { return t.Key }, func(t KeyValue[int, bool]) bool { return t.Value }, - )(FromMap[int, bool](input)) + )(FromMap(input)) if !reflect.DeepEqual(result, input) { t.Errorf("From(%v).ToMapBy()=%v expected %v", input, result, input) @@ -635,7 +636,7 @@ func TestToSlice(t *testing.T) { } for _, test := range tests { - test.output = ToSlice[int](FromSlice[int](test.input)) + test.output = ToSlice(FromSlice(test.input)) // test slice values assert.DeepEqual(t, test.output, test.want) diff --git a/reverse_test.go b/reverse_test.go index bb37f66..e8211aa 100644 --- a/reverse_test.go +++ b/reverse_test.go @@ -12,8 +12,8 @@ func TestReverse(t *testing.T) { for _, test := range tests { - if q := Reverse[int](FromSlice[int](test.input)); !validateQuery(q, test.want) { - t.Errorf("From(%v).Reverse()=%v expected %v", test.input, toSlice(q), test.want) + if q := Reverse(FromSlice(test.input)); !ValidateQuery(q, test.want) { + t.Errorf("From(%v).Reverse()=%v expected %v", test.input, ToSlice(q), test.want) } } } diff --git a/select_test.go b/select_test.go index 5b5ee33..0e2d0ba 100644 --- a/select_test.go +++ b/select_test.go @@ -19,8 +19,8 @@ func TestSelect(t *testing.T) { for _, test := range tests { - if q := Select[int](test.selector)(FromSlice[int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).Select()=%v expected %v", test.input, toSlice(q), test.output) + if q := Select(test.selector)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Select()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -38,8 +38,8 @@ func TestSelect(t *testing.T) { for _, test := range tests { - if q := Select[rune, string](test.selector)(FromString(test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).Select()=%v expected %v", test.input, toSlice(q), test.output) + if q := Select(test.selector)(FromString(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Select()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -59,8 +59,8 @@ func TestSelectIndexed(t *testing.T) { for _, test := range tests { - if q := SelectIndexed[int, int](test.selector)(FromSlice[int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SelectIndexed()=%v expected %v", test.input, toSlice(q), test.output) + if q := SelectIndexed(test.selector)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SelectIndexed()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -78,8 +78,8 @@ func TestSelectIndexed(t *testing.T) { for _, test := range tests { - if q := SelectIndexed[rune, string](test.selector)(FromString(test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SelectIndexed()=%v expected %v", test.input, toSlice(q), test.output) + if q := SelectIndexed(test.selector)(FromString(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SelectIndexed()=%v expected %v", test.input, ToSlice(q), test.output) } } } diff --git a/selectmany_test.go b/selectmany_test.go index 49e94f0..920f75f 100644 --- a/selectmany_test.go +++ b/selectmany_test.go @@ -19,8 +19,8 @@ func TestSelectMany(t *testing.T) { } for _, test := range tests { - if q := SelectMany[string, rune](test.selector)(FromSlice[string](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SelectMany()=%v expected %v", test.input, toSlice(q), test.output) + if q := SelectMany(test.selector)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SelectMany()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -32,13 +32,13 @@ func TestSelectMany(t *testing.T) { }{ {[][]int{{1, 2, 3}, {4, 5, 6, 7}}, func(i []int) Query[int] { - return FromSlice[int](i) + return FromSlice(i) }, []int{1, 2, 3, 4, 5, 6, 7}}, } for _, test := range tests { - if q := SelectMany[[]int, int](test.selector)(FromSlice[[]int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SelectMany()=%v expected %v", test.input, toSlice(q), test.output) + if q := SelectMany(test.selector)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SelectMany()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -61,8 +61,8 @@ func TestSelectManyIndexed(t *testing.T) { for _, test := range tests { - if q := SelectManyIndexed[[]int, int](test.selector)(FromSlice[[]int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SelectManyIndexed()=%v expected %v", test.input, toSlice(q), test.output) + if q := SelectManyIndexed(test.selector)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SelectManyIndexed()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -81,8 +81,8 @@ func TestSelectManyIndexed(t *testing.T) { for _, test := range tests { - if q := SelectManyIndexed[string, rune](test.selector)(FromSlice[string](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SelectManyIndexed()=%v expected %v", test.input, toSlice(q), test.output) + if q := SelectManyIndexed(test.selector)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SelectManyIndexed()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -98,7 +98,7 @@ func TestSelectManyBy(t *testing.T) { }{ {[][]int{{1, 2, 3}, {4, 5, 6, 7}}, func(i []int) Query[int] { - return FromSlice[int](i) + return FromSlice(i) }, func(x int, y []int) int { return x + 1 }, []int{2, 3, 4, 5, 6, 7, 8}}, @@ -106,8 +106,8 @@ func TestSelectManyBy(t *testing.T) { for _, test := range tests { - if q := SelectManyBy[[]int, int, int](test.selector, test.resultSelector)(FromSlice[[]int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SelectManyBy()=%v expected %v", test.input, toSlice(q), test.output) + if q := SelectManyBy(test.selector, test.resultSelector)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SelectManyBy()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -128,8 +128,8 @@ func TestSelectManyBy(t *testing.T) { } for _, test := range tests { - if q := SelectManyBy[string, rune, string](test.selector, test.resultSelector)(FromSlice[string](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SelectManyBy()=%v expected %v", test.input, toSlice(q), test.output) + if q := SelectManyBy(test.selector, test.resultSelector)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SelectManyBy()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -146,17 +146,17 @@ func TestSelectManyIndexedBy(t *testing.T) { {[][]int{{1, 2, 3}, {4, 5, 6, 7}}, func(i int, x []int) Query[int] { if i == 0 { - return FromSlice[int]([]int{10, 20, 30}) + return FromSlice([]int{10, 20, 30}) } - return FromSlice[int](x) + return FromSlice(x) }, func(x int, y []int) int { return x + 1 }, []int{11, 21, 31, 5, 6, 7, 8}}, } for _, test := range tests { - if q := SelectManyByIndexed[[]int, int, int](test.selector, test.resultSelector)(FromSlice[[]int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SelectManyIndexedBy()=%v expected %v", test.input, toSlice(q), test.output) + if q := SelectManyByIndexed(test.selector, test.resultSelector)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SelectManyIndexedBy()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -181,8 +181,8 @@ func TestSelectManyIndexedBy(t *testing.T) { for _, test := range tests { - if q := SelectManyByIndexed[string, rune, string](test.selector, test.resultSelector)(FromSlice[string](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SelectManyIndexedBy()=%v expected %v", test.input, toSlice(q), test.output) + if q := SelectManyByIndexed(test.selector, test.resultSelector)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SelectManyIndexedBy()=%v expected %v", test.input, ToSlice(q), test.output) } } } diff --git a/setup_test.go b/setup_test.go index ab4bfaf..22a224c 100644 --- a/setup_test.go +++ b/setup_test.go @@ -13,36 +13,3 @@ func getF1(f foo) int { func getF2(f foo) bool { return f.f2 } -func getF3(f foo) string { - return f.f3 -} - -func getSelf[T any](t T) T { - return t -} - -func toSlice[T any](q Query[T]) (result []T) { - next := q.Iterate() - - for item, ok := next(); ok; item, ok = next() { - result = append(result, item) - } - - return -} - -func validateQuery[T comparable](q Query[T], output []T) bool { - next := q.Iterate() - - for _, oitem := range output { - qitem, _ := next() - - if oitem != qitem { - return false - } - } - - _, ok := next() - _, ok2 := next() - return !(ok || ok2) -} diff --git a/skip.go b/skip.go index 6fbb587..4d450e4 100644 --- a/skip.go +++ b/skip.go @@ -2,26 +2,24 @@ package flinx // Skip bypasses a specified number of elements in a collection and then returns // the remaining elements. -func Skip[T any](count int) func(q Query[T]) Query[T] { - - return func(q Query[T]) Query[T] { - return Query[T]{ - Iterate: func() Iterator[T] { - next := q.Iterate() - n := count - - return func() (item T, ok bool) { - for ; n > 0; n-- { - item, ok = next() - if !ok { - return - } +func Skip[T any](q Query[T], count int) Query[T] { + + return Query[T]{ + Iterate: func() Iterator[T] { + next := q.Iterate() + n := count + + return func() (item T, ok bool) { + for ; n > 0; n-- { + item, ok = next() + if !ok { + return } - - return next() } - }, - } + + return next() + } + }, } } diff --git a/skip_test.go b/skip_test.go index 15ecf82..3de0669 100644 --- a/skip_test.go +++ b/skip_test.go @@ -1,8 +1,9 @@ package flinx import ( - "gotest.tools/v3/assert" "testing" + + "gotest.tools/v3/assert" ) func TestSkip(t *testing.T) { @@ -18,7 +19,7 @@ func TestSkip(t *testing.T) { } for _, test := range tests { - res := ToSlice[int](Skip[int](3)(FromSlice[int](test.input))) + res := ToSlice(Skip(FromSlice(test.input), 3)) assert.DeepEqual(t, res, test.output) } @@ -33,7 +34,7 @@ func TestSkip(t *testing.T) { } for _, test := range tests { - res := ToSlice[rune](Skip[rune](3)(FromString(test.input))) + res := ToSlice(Skip(FromString(test.input), 3)) assert.DeepEqual(t, res, test.output) } @@ -61,8 +62,8 @@ func TestSkipWhile(t *testing.T) { for _, test := range tests { - if q := SkipWhile[int](test.predicate)(FromSlice[int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SkipWhile()=%v expected %v", test.input, toSlice(q), test.output) + if q := SkipWhile(test.predicate)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SkipWhile()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -80,8 +81,8 @@ func TestSkipWhile(t *testing.T) { } for _, test := range tests { - if q := SkipWhile[rune](test.predicate)(FromString(test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SkipWhile()=%v expected %v", test.input, toSlice(q), test.output) + if q := SkipWhile(test.predicate)(FromString(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SkipWhile()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -108,8 +109,8 @@ func TestSkipWhileIndexed(t *testing.T) { for _, test := range tests { - if q := SkipWhileIndexed[int](test.predicate)(FromSlice[int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SkipWhileIndexed()=%v expected %v", test.input, toSlice(q), test.output) + if q := SkipWhileIndexed(test.predicate)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SkipWhileIndexed()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -128,8 +129,8 @@ func TestSkipWhileIndexed(t *testing.T) { for _, test := range tests { - if q := SkipWhileIndexed[rune](test.predicate)(FromString(test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).SkipWhileIndexed()=%v expected %v", test.input, toSlice(q), test.output) + if q := SkipWhileIndexed(test.predicate)(FromString(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).SkipWhileIndexed()=%v expected %v", test.input, ToSlice(q), test.output) } } } diff --git a/take.go b/take.go index d34ef3e..03bb95c 100644 --- a/take.go +++ b/take.go @@ -2,24 +2,22 @@ package flinx // Take returns a specified number of contiguous elements from the start of a // collection. -func Take[T any](count int) func(q Query[T]) Query[T] { +func Take[T any](q Query[T], count int) Query[T] { - return func(q Query[T]) Query[T] { - return Query[T]{ - Iterate: func() Iterator[T] { - next := q.Iterate() - n := count + return Query[T]{ + Iterate: func() Iterator[T] { + next := q.Iterate() + n := count - return func() (item T, ok bool) { - if n <= 0 { - return - } - - n-- - return next() + return func() (item T, ok bool) { + if n <= 0 { + return } - }, - } + + n-- + return next() + } + }, } } diff --git a/take_test.go b/take_test.go index 74b7863..aec35ad 100644 --- a/take_test.go +++ b/take_test.go @@ -14,8 +14,8 @@ func TestTake(t *testing.T) { for _, test := range tests { - if q := Take[int](3)(FromSlice[int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).Take(3)=%v expected %v", test.input, toSlice(q), test.output) + if q := Take(FromSlice(test.input), 3); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Take(3)=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -29,8 +29,8 @@ func TestTake(t *testing.T) { } for _, test := range tests { - if q := Take[rune](3)(FromString(test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).Take(3)=%v expected %v", test.input, toSlice(q), test.output) + if q := Take(FromString(test.input), 3); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Take(3)=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -54,8 +54,8 @@ func TestTakeWhile(t *testing.T) { for _, test := range tests { - if q := TakeWhile[int](test.predicate)(FromSlice[int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).Take(3)=%v expected %v", test.input, toSlice(q), test.output) + if q := TakeWhile(test.predicate)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Take(3)=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -72,8 +72,8 @@ func TestTakeWhile(t *testing.T) { } for _, test := range tests { - if q := TakeWhile[rune](test.predicate)(FromString(test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).Take(3)=%v expected %v", test.input, toSlice(q), test.output) + if q := TakeWhile(test.predicate)(FromString(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Take(3)=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -97,8 +97,8 @@ func TestTakeWhileIndexed(t *testing.T) { for _, test := range tests { - if q := TakeWhileIndexed[int](test.predicate)(FromSlice[int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).Take(3)=%v expected %v", test.input, toSlice(q), test.output) + if q := TakeWhileIndexed(test.predicate)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Take(3)=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -115,8 +115,8 @@ func TestTakeWhileIndexed(t *testing.T) { for _, test := range tests { - if q := TakeWhileIndexed[rune](test.predicate)(FromString(test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).Take(3)=%v expected %v", test.input, toSlice(q), test.output) + if q := TakeWhileIndexed(test.predicate)(FromString(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Take(3)=%v expected %v", test.input, ToSlice(q), test.output) } } } diff --git a/union_test.go b/union_test.go index 0c833a9..11a6471 100644 --- a/union_test.go +++ b/union_test.go @@ -7,7 +7,7 @@ func TestUnion(t *testing.T) { input2 := []int{2, 4, 5, 1} want := []int{1, 2, 3, 4, 5} - if q := Union[int](FromSlice[int](input1), FromSlice[int](input2)); !validateQuery(q, want) { - t.Errorf("From(%v).Union(%v)=%v expected %v", input1, input2, toSlice(q), want) + if q := Union(FromSlice(input1), FromSlice(input2)); !ValidateQuery(q, want) { + t.Errorf("From(%v).Union(%v)=%v expected %v", input1, input2, ToSlice(q), want) } } diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..83a71c4 --- /dev/null +++ b/utils.go @@ -0,0 +1,21 @@ +package flinx + +func Self[T any](t T) T { + return t +} + +func ValidateQuery[T comparable](q Query[T], output []T) bool { + next := q.Iterate() + + for _, oitem := range output { + qitem, _ := next() + + if oitem != qitem { + return false + } + } + + _, ok := next() + _, ok2 := next() + return !(ok || ok2) +} diff --git a/where.go b/where.go index ec7b4a9..b14a24e 100644 --- a/where.go +++ b/where.go @@ -4,7 +4,7 @@ func Where[T any](predicate func(T) bool) func(q Query[T]) Query[T] { //predicateIdx := func(_ int, item T) bool { // return predicate(item) //} - //return WhereIndexed[T](predicateIdx) + //return WhereIndexed(predicateIdx) return func(q Query[T]) Query[T] { return Query[T]{ Iterate: func() Iterator[T] { diff --git a/where_test.go b/where_test.go index dd80e4a..0991245 100644 --- a/where_test.go +++ b/where_test.go @@ -17,8 +17,8 @@ func TestWhere(t *testing.T) { for _, test := range tests { - if q := Where[int](test.predicate)(FromSlice[int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).Where()=%v expected %v", test.input, toSlice(q), test.output) + if q := Where(test.predicate)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Where()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -37,8 +37,8 @@ func TestWhere(t *testing.T) { for _, test := range tests { - if q := Where[rune](test.predicate)(FromString(test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).Where()=%v expected %v", test.input, toSlice(q), test.output) + if q := Where(test.predicate)(FromString(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).Where()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -59,8 +59,8 @@ func TestWhereIndexed(t *testing.T) { for _, test := range tests { - if q := WhereIndexed[int](test.predicate)(FromSlice[int](test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).WhereIndexed()=%v expected %v", test.input, toSlice(q), test.output) + if q := WhereIndexed(test.predicate)(FromSlice(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).WhereIndexed()=%v expected %v", test.input, ToSlice(q), test.output) } } } @@ -81,8 +81,8 @@ func TestWhereIndexed(t *testing.T) { for _, test := range tests { - if q := WhereIndexed[rune](test.predicate)(FromString(test.input)); !validateQuery(q, test.output) { - t.Errorf("From(%v).WhereIndexed()=%v expected %v", test.input, toSlice(q), test.output) + if q := WhereIndexed(test.predicate)(FromString(test.input)); !ValidateQuery(q, test.output) { + t.Errorf("From(%v).WhereIndexed()=%v expected %v", test.input, ToSlice(q), test.output) } } } diff --git a/zip_test.go b/zip_test.go index aede287..3b70f34 100644 --- a/zip_test.go +++ b/zip_test.go @@ -7,9 +7,9 @@ func TestZip(t *testing.T) { input2 := []int{2, 4, 5, 1} want := []int{3, 6, 8} - if q := Zip[int, int, int](func(i, j int) int { + if q := Zip(func(i, j int) int { return i + j - })(FromSlice[int](input1), FromSlice[int](input2)); !validateQuery(q, want) { - t.Errorf("From(%v).Zip(%v)=%v expected %v", input1, input2, toSlice(q), want) + })(FromSlice(input1), FromSlice(input2)); !ValidateQuery(q, want) { + t.Errorf("From(%v).Zip(%v)=%v expected %v", input1, input2, ToSlice(q), want) } }