From 1343683b08481824c0ba7eb965c267d0702def7c Mon Sep 17 00:00:00 2001 From: dudaodong Date: Fri, 7 Jan 2022 17:48:00 +0800 Subject: [PATCH] checkout v2 branch for generics migration --- go.mod | 2 +- myconstraints/constraints.go | 6 ++++ slice/slice.go | 59 +++++++++++------------------------- slice/slice_test.go | 18 ++++++----- 4 files changed, 35 insertions(+), 50 deletions(-) create mode 100644 myconstraints/constraints.go diff --git a/go.mod b/go.mod index 02610a3..29360f4 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/duke-git/lancet -go 1.16 +go 1.18 diff --git a/myconstraints/constraints.go b/myconstraints/constraints.go new file mode 100644 index 0000000..eeca350 --- /dev/null +++ b/myconstraints/constraints.go @@ -0,0 +1,6 @@ +package myconstraints + + +type Number interface { + int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr | float32 | float64 | complex64 | complex128 +} diff --git a/slice/slice.go b/slice/slice.go index 8df6748..39a61c6 100644 --- a/slice/slice.go +++ b/slice/slice.go @@ -166,25 +166,15 @@ func Some(slice, function interface{}) bool { } // Filter iterates over elements of slice, returning an slice of all elements `signature` returns truthy for. -// The function signature should be func(index int, value interface{}) bool . -func Filter(slice, function interface{}) interface{} { - sv := sliceValue(slice) - fn := functionValue(function) - - elemType := sv.Type().Elem() - if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) { - panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String()) - } - - res := reflect.MakeSlice(sv.Type(), 0, 0) - for i := 0; i < sv.Len(); i++ { - flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0] - if flag.Bool() { - res = reflect.Append(res, sv.Index(i)) +// The fn signature should be func(int, T) bool. +func Filter[T any](slice []T, fn func(index int, t T) bool) []T { + res := make([]T, 0, 0) + for i, v := range slice { + if fn(i, v) { + res = append(res, v) } } - - return res.Interface() + return res } // Count iterates over elements of slice, returns a count of all matched elements @@ -288,37 +278,22 @@ func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value { } // ForEach iterates over elements of slice and invokes function for each element -// The function signature should be func(index int, value interface{}). -func ForEach(slice, function interface{}) { - sv := sliceValue(slice) - fn := functionValue(function) - - elemType := sv.Type().Elem() - if checkSliceCallbackFuncSignature(fn, elemType, nil) { - panic("function param should be of type func(int, " + elemType.String() + ")" + elemType.String()) - } - - for i := 0; i < sv.Len(); i++ { - fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)}) +// The fn signature should be func(int, T ). +func ForEach[T any] (slice []T, fn func(index int, t T)) { + for i, v := range slice { + fn(i, v) } } // Map creates an slice of values by running each element of `slice` thru `function`. -// The function signature should be func(index int, value interface{}) interface{}. -func Map(slice, function interface{}) interface{} { - sv := sliceValue(slice) - fn := functionValue(function) - - elemType := sv.Type().Elem() - if checkSliceCallbackFuncSignature(fn, elemType, nil) { - panic("function param should be of type func(int, " + elemType.String() + ")" + elemType.String()) +// The fn signature should be func(int, T). +func Map[T any, U any](slice []T, fn func(index int, t T) U) []U { + res := make([]U, len(slice), cap(slice)) + for i, v := range slice { + res[i] = fn(i, v) } - res := reflect.MakeSlice(sv.Type(), sv.Len(), sv.Len()) - for i := 0; i < sv.Len(); i++ { - res.Index(i).Set(fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]) - } - return res.Interface() + return res } // Reduce creates an slice of values by running each element of `slice` thru `function`. diff --git a/slice/slice_test.go b/slice/slice_test.go index db28b10..c528535 100644 --- a/slice/slice_test.go +++ b/slice/slice_test.go @@ -253,9 +253,11 @@ func TestForEach(t *testing.T) { expected := []int{3, 4, 5, 6, 7} var numbersAddTwo []int - ForEach(numbers, func(index int, value int) { + addTwo := func(index int, value int) { numbersAddTwo = append(numbersAddTwo, value+2) - }) + } + + ForEach(numbers, addTwo) if !reflect.DeepEqual(numbersAddTwo, expected) { internal.LogFailedTestInfo(t, "ForEach", numbers, expected, numbersAddTwo) @@ -265,14 +267,16 @@ func TestForEach(t *testing.T) { } func TestMap(t *testing.T) { - s1 := []int{1, 2, 3, 4} + numbers := []int{1, 2, 3, 4} multiplyTwo := func(i, num int) int { return num * 2 } - e1 := []int{2, 4, 6, 8} - r1 := Map(s1, multiplyTwo) - if !reflect.DeepEqual(r1, e1) { - internal.LogFailedTestInfo(t, "Map", s1, e1, r1) + + expected := []int{2, 4, 6, 8} + actual := Map(numbers, multiplyTwo) + + if !reflect.DeepEqual(actual, expected) { + internal.LogFailedTestInfo(t, "Map", numbers, expected, actual) t.FailNow() }