-
Notifications
You must be signed in to change notification settings - Fork 0
/
all.go
83 lines (63 loc) · 1.88 KB
/
all.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package functools
import (
"reflect"
"errors"
)
/*
'All' function returns 'true' if all elements of iterable 'slice' are 'true'
or if the slice is empty. Each element of the slice is converted to bool
by 'functools.ToBool' function. Function allowes slices and arrays.
All(slice) bool
AllSafe(slice) (bool, err)
'AllFunc' function applies 'func' parameter for each element of the iterable 'slice'
and returns 'true' if all results of 'func' calling are 'true' or if the slice is empty.
Function allowes slices and arrays.
AllFunc(func, slice) bool
AllFuncSafe(func, slice) (bool, err)
*/
func all(function, slice interface{}) bool {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice && rv.Kind() != reflect.Array {
raise(errors.New("The passed collection is not a slice or an array"), "All")
}
fn := reflect.ValueOf(function)
t := rv.Type().Elem()
if !verifyAllFuncType(fn, t) {
raise(errors.New("Function must be of type func(" + t.String() +
") bool or func(interface{}) bool"), "All")
}
var param [1]reflect.Value
for i := 0; i < rv.Len(); i++ {
param[0] = rv.Index(i)
if !fn.Call(param[:])[0].Bool() {
return false
}
}
return true
}
func verifyAllFuncType(fn reflect.Value, elType reflect.Type) bool {
if fn.Kind() != reflect.Func {
return false
}
if fn.Type().NumIn() != 1 || fn.Type().NumOut() != 1 {
return false
}
return ((fn.Type().In(0).Kind() == reflect.Interface || fn.Type().In(0) == elType) &&
fn.Type().Out(0).Kind() == reflect.Bool)
}
func All(slice interface{}) bool {
return all(ToBool, slice)
}
func AllSafe(slice interface{}) (result bool, err error) {
defer except(&err)
result = all(ToBool, slice)
return
}
func AllFunc(function, slice interface{}) bool {
return all(function, slice)
}
func AllFuncSafe(function, slice interface{}) (result bool, err error) {
defer except(&err)
result = all(function, slice)
return
}