diff --git a/README.rst b/README.rst index 4f6d59c..d1a9f85 100644 --- a/README.rst +++ b/README.rst @@ -601,12 +601,18 @@ funk.ForEach Range over an iteratee (map, slice). +Or update element in slice(Not map, reflect#Value#MapIndex#CanSet is false). + .. code-block:: go funk.ForEach([]int{1, 2, 3, 4}, func(x int) { fmt.Println(x) }) + foo := []int{1,2,3} + funk.ForEach(foo, func(x *int){ *x = *x * 2}) + fmt.Println(foo) // []int{2, 4, 6} + funk.ForEachRight ............ diff --git a/scan.go b/scan.go index d0d1d45..197330f 100644 --- a/scan.go +++ b/scan.go @@ -25,14 +25,20 @@ func ForEach(arr interface{}, predicate interface{}) { } arrElemType := arrValue.Type().Elem() + arrElemPointerType := reflect.New(arrElemType).Type() + usePointer := arrElemPointerType.ConvertibleTo(funcType.In(0)) // Checking whether element type is convertible to function's first argument's type. - if !arrElemType.ConvertibleTo(funcType.In(0)) { + if !arrElemType.ConvertibleTo(funcType.In(0)) && !usePointer { panic("Map function's argument is not compatible with type of array.") } for i := 0; i < arrValue.Len(); i++ { - funcValue.Call([]reflect.Value{arrValue.Index(i)}) + if usePointer { + funcValue.Call([]reflect.Value{arrValue.Index(i).Addr()}) + } else { + funcValue.Call([]reflect.Value{arrValue.Index(i)}) + } } } @@ -79,14 +85,21 @@ func ForEachRight(arr interface{}, predicate interface{}) { } arrElemType := arrValue.Type().Elem() + arrElemPointerType := reflect.New(arrElemType).Type() + usePointer := arrElemPointerType.ConvertibleTo(funcType.In(0)) // Checking whether element type is convertible to function's first argument's type. - if !arrElemType.ConvertibleTo(funcType.In(0)) { + if !arrElemType.ConvertibleTo(funcType.In(0)) && !usePointer { panic("Map function's argument is not compatible with type of array.") } for i := arrValue.Len() - 1; i >= 0; i-- { - funcValue.Call([]reflect.Value{arrValue.Index(i)}) + if usePointer { + funcValue.Call([]reflect.Value{arrValue.Index(i).Addr()}) + } else { + funcValue.Call([]reflect.Value{arrValue.Index(i)}) + } + } } diff --git a/scan_test.go b/scan_test.go index 55b03f2..8fc8faf 100644 --- a/scan_test.go +++ b/scan_test.go @@ -19,6 +19,23 @@ func TestForEach(t *testing.T) { is.Equal(results, []int{2, 4}) + toModify := []int{1, 2, 3} + ForEach(toModify, func(x *int) { *x = *x * 2 }) + + is.Equal(toModify, []int{2, 4, 6}) + + toModify = []int{} + ForEach(toModify, func(x *int) {}) + + is.Equal(toModify, []int{}) + + strModify := []string{"a", "b"} + ForEach(strModify, func(s *string) { + *s = *s + *s + }) + + is.Equal(strModify, []string{"aa", "bb"}) + mapping := map[int]string{ 1: "Florent", 2: "Gilles", @@ -40,6 +57,23 @@ func TestForEachRight(t *testing.T) { is.Equal(results, []int{8, 6, 4, 2}) + toModify := []int{1, 2, 3} + ForEach(toModify, func(x *int) { *x = *x * 2 }) + + is.Equal(toModify, []int{2, 4, 6}) + + toModify = []int{} + ForEach(toModify, func(x *int) {}) + + is.Equal(toModify, []int{}) + + strModify := []string{"a", "b"} + ForEach(strModify, func(s *string) { + *s = *s + *s + }) + + is.Equal(strModify, []string{"aa", "bb"}) + mapping := map[int]string{ 1: "Florent", 2: "Gilles",