...
1 package funk
2
3 import (
4 "fmt"
5 "reflect"
6 )
7
8
9
10 func ForEach(arr interface{}, predicate interface{}) {
11 if !IsIteratee(arr) {
12 panic("First parameter must be an iteratee")
13 }
14
15 var (
16 funcValue = reflect.ValueOf(predicate)
17 arrValue = reflect.ValueOf(arr)
18 arrType = arrValue.Type()
19 funcType = funcValue.Type()
20 )
21
22 if arrType.Kind() == reflect.Slice || arrType.Kind() == reflect.Array {
23 if !IsFunction(predicate, 1, 0) {
24 panic("Second argument must be a function with one parameter")
25 }
26
27 arrElemType := arrValue.Type().Elem()
28
29
30 if !arrElemType.ConvertibleTo(funcType.In(0)) {
31 panic("Map function's argument is not compatible with type of array.")
32 }
33
34 for i := 0; i < arrValue.Len(); i++ {
35 funcValue.Call([]reflect.Value{arrValue.Index(i)})
36 }
37 }
38
39 if arrType.Kind() == reflect.Map {
40 if !IsFunction(predicate, 2, 0) {
41 panic("Second argument must be a function with two parameters")
42 }
43
44
45 keyType := arrType.Key()
46 valueType := arrType.Elem()
47
48 if !keyType.ConvertibleTo(funcType.In(0)) {
49 panic(fmt.Sprintf("function first argument is not compatible with %s", keyType.String()))
50 }
51
52 if !valueType.ConvertibleTo(funcType.In(1)) {
53 panic(fmt.Sprintf("function second argument is not compatible with %s", valueType.String()))
54 }
55
56 for _, key := range arrValue.MapKeys() {
57 funcValue.Call([]reflect.Value{key, arrValue.MapIndex(key)})
58 }
59 }
60 }
61
62
63
64 func ForEachRight(arr interface{}, predicate interface{}) {
65 if !IsIteratee(arr) {
66 panic("First parameter must be an iteratee")
67 }
68
69 var (
70 funcValue = reflect.ValueOf(predicate)
71 arrValue = reflect.ValueOf(arr)
72 arrType = arrValue.Type()
73 funcType = funcValue.Type()
74 )
75
76 if arrType.Kind() == reflect.Slice || arrType.Kind() == reflect.Array {
77 if !IsFunction(predicate, 1, 0) {
78 panic("Second argument must be a function with one parameter")
79 }
80
81 arrElemType := arrValue.Type().Elem()
82
83
84 if !arrElemType.ConvertibleTo(funcType.In(0)) {
85 panic("Map function's argument is not compatible with type of array.")
86 }
87
88 for i := arrValue.Len() - 1; i >= 0; i-- {
89 funcValue.Call([]reflect.Value{arrValue.Index(i)})
90 }
91 }
92
93 if arrType.Kind() == reflect.Map {
94 if !IsFunction(predicate, 2, 0) {
95 panic("Second argument must be a function with two parameters")
96 }
97
98
99 keyType := arrType.Key()
100 valueType := arrType.Elem()
101
102 if !keyType.ConvertibleTo(funcType.In(0)) {
103 panic(fmt.Sprintf("function first argument is not compatible with %s", keyType.String()))
104 }
105
106 if !valueType.ConvertibleTo(funcType.In(1)) {
107 panic(fmt.Sprintf("function second argument is not compatible with %s", valueType.String()))
108 }
109
110 keys := Reverse(arrValue.MapKeys()).([]reflect.Value)
111
112 for _, key := range keys {
113 funcValue.Call([]reflect.Value{key, arrValue.MapIndex(key)})
114 }
115 }
116 }
117
118
119 func Head(arr interface{}) interface{} {
120 value := redirectValue(reflect.ValueOf(arr))
121 valueType := value.Type()
122
123 kind := value.Kind()
124
125 if kind == reflect.Array || kind == reflect.Slice {
126 if value.Len() == 0 {
127 return nil
128 }
129
130 return value.Index(0).Interface()
131 }
132
133 panic(fmt.Sprintf("Type %s is not supported by Head", valueType.String()))
134 }
135
136
137 func Last(arr interface{}) interface{} {
138 value := redirectValue(reflect.ValueOf(arr))
139 valueType := value.Type()
140
141 kind := value.Kind()
142
143 if kind == reflect.Array || kind == reflect.Slice {
144 if value.Len() == 0 {
145 return nil
146 }
147
148 return value.Index(value.Len() - 1).Interface()
149 }
150
151 panic(fmt.Sprintf("Type %s is not supported by Last", valueType.String()))
152 }
153
154
155 func Initial(arr interface{}) interface{} {
156 value := redirectValue(reflect.ValueOf(arr))
157 valueType := value.Type()
158
159 kind := value.Kind()
160
161 if kind == reflect.Array || kind == reflect.Slice {
162 length := value.Len()
163
164 if length <= 1 {
165 return arr
166 }
167
168 return value.Slice(0, length-1).Interface()
169 }
170
171 panic(fmt.Sprintf("Type %s is not supported by Initial", valueType.String()))
172 }
173
174
175 func Tail(arr interface{}) interface{} {
176 value := redirectValue(reflect.ValueOf(arr))
177 valueType := value.Type()
178
179 kind := value.Kind()
180
181 if kind == reflect.Array || kind == reflect.Slice {
182 length := value.Len()
183
184 if length <= 1 {
185 return arr
186 }
187
188 return value.Slice(1, length).Interface()
189 }
190
191 panic(fmt.Sprintf("Type %s is not supported by Initial", valueType.String()))
192 }
193
View as plain text