Skip to content

Commit 42808ee

Browse files
authored
Merge pull request #153 from ethahae/master
ForEach slice modify(optional)
2 parents e7efff4 + 8de891d commit 42808ee

3 files changed

Lines changed: 57 additions & 4 deletions

File tree

README.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,12 +601,18 @@ funk.ForEach
601601

602602
Range over an iteratee (map, slice).
603603

604+
Or update element in slice(Not map, reflect#Value#MapIndex#CanSet is false).
605+
604606
.. code-block:: go
605607
606608
funk.ForEach([]int{1, 2, 3, 4}, func(x int) {
607609
fmt.Println(x)
608610
})
609611
612+
foo := []int{1,2,3}
613+
funk.ForEach(foo, func(x *int){ *x = *x * 2})
614+
fmt.Println(foo) // []int{2, 4, 6}
615+
610616
funk.ForEachRight
611617
............
612618

scan.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,20 @@ func ForEach(arr interface{}, predicate interface{}) {
2525
}
2626

2727
arrElemType := arrValue.Type().Elem()
28+
arrElemPointerType := reflect.New(arrElemType).Type()
29+
usePointer := arrElemPointerType.ConvertibleTo(funcType.In(0))
2830

2931
// Checking whether element type is convertible to function's first argument's type.
30-
if !arrElemType.ConvertibleTo(funcType.In(0)) {
32+
if !arrElemType.ConvertibleTo(funcType.In(0)) && !usePointer {
3133
panic("Map function's argument is not compatible with type of array.")
3234
}
3335

3436
for i := 0; i < arrValue.Len(); i++ {
35-
funcValue.Call([]reflect.Value{arrValue.Index(i)})
37+
if usePointer {
38+
funcValue.Call([]reflect.Value{arrValue.Index(i).Addr()})
39+
} else {
40+
funcValue.Call([]reflect.Value{arrValue.Index(i)})
41+
}
3642
}
3743
}
3844

@@ -79,14 +85,21 @@ func ForEachRight(arr interface{}, predicate interface{}) {
7985
}
8086

8187
arrElemType := arrValue.Type().Elem()
88+
arrElemPointerType := reflect.New(arrElemType).Type()
89+
usePointer := arrElemPointerType.ConvertibleTo(funcType.In(0))
8290

8391
// Checking whether element type is convertible to function's first argument's type.
84-
if !arrElemType.ConvertibleTo(funcType.In(0)) {
92+
if !arrElemType.ConvertibleTo(funcType.In(0)) && !usePointer {
8593
panic("Map function's argument is not compatible with type of array.")
8694
}
8795

8896
for i := arrValue.Len() - 1; i >= 0; i-- {
89-
funcValue.Call([]reflect.Value{arrValue.Index(i)})
97+
if usePointer {
98+
funcValue.Call([]reflect.Value{arrValue.Index(i).Addr()})
99+
} else {
100+
funcValue.Call([]reflect.Value{arrValue.Index(i)})
101+
}
102+
90103
}
91104
}
92105

scan_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@ func TestForEach(t *testing.T) {
1919

2020
is.Equal(results, []int{2, 4})
2121

22+
toModify := []int{1, 2, 3}
23+
ForEach(toModify, func(x *int) { *x = *x * 2 })
24+
25+
is.Equal(toModify, []int{2, 4, 6})
26+
27+
toModify = []int{}
28+
ForEach(toModify, func(x *int) {})
29+
30+
is.Equal(toModify, []int{})
31+
32+
strModify := []string{"a", "b"}
33+
ForEach(strModify, func(s *string) {
34+
*s = *s + *s
35+
})
36+
37+
is.Equal(strModify, []string{"aa", "bb"})
38+
2239
mapping := map[int]string{
2340
1: "Florent",
2441
2: "Gilles",
@@ -40,6 +57,23 @@ func TestForEachRight(t *testing.T) {
4057

4158
is.Equal(results, []int{8, 6, 4, 2})
4259

60+
toModify := []int{1, 2, 3}
61+
ForEach(toModify, func(x *int) { *x = *x * 2 })
62+
63+
is.Equal(toModify, []int{2, 4, 6})
64+
65+
toModify = []int{}
66+
ForEach(toModify, func(x *int) {})
67+
68+
is.Equal(toModify, []int{})
69+
70+
strModify := []string{"a", "b"}
71+
ForEach(strModify, func(s *string) {
72+
*s = *s + *s
73+
})
74+
75+
is.Equal(strModify, []string{"aa", "bb"})
76+
4377
mapping := map[int]string{
4478
1: "Florent",
4579
2: "Gilles",

0 commit comments

Comments
 (0)