//Check it is a funciton if fn.Kind() != reflect.Func { returnfalse } // NumIn() - returns a function type's input parameter count. // NumOut() - returns a function type's output parameter count. if (fn.Type().NumIn() != len(types)-1) || (fn.Type().NumOut() != 1) { returnfalse } // In() - returns the type of a function type's i'th input parameter. for i := 0; i < len(types)-1; i++ { if fn.Type().In(i) != types[i] { returnfalse } } // Out() - returns the type of a function type's i'th output parameter. outType := types[len(types)-1] if outType != nil && fn.Type().Out(0) != outType { returnfalse } returntrue }
funcReduce(slice, pairFunc, zero interface{})interface{} { sliceInType := reflect.ValueOf(slice) if sliceInType.Kind() != reflect.Slice { panic("reduce: wrong type, not slice") }
len := sliceInType.Len() iflen == 0 { return zero } elseiflen == 1 { return sliceInType.Index(0) }
elemType := sliceInType.Type().Elem() fn := reflect.ValueOf(pairFunc) if !verifyFuncSignature(fn, elemType, elemType, elemType) { t := elemType.String() panic("reduce: function must be of type func(" + t + ", " + t + ") " + t) }
var ins [2]reflect.Value ins[0] = sliceInType.Index(0) ins[1] = sliceInType.Index(1) out := fn.Call(ins[:])[0]
for i := 2; i < len; i++ { ins[0] = out ins[1] = sliceInType.Index(i) out = fn.Call(ins[:])[0] } return out.Interface() }
funcFilter(slice, function interface{})interface{} { result, _ := filter(slice, function, false) return result }
funcFilterInPlace(slicePtr, function interface{}) { in := reflect.ValueOf(slicePtr) if in.Kind() != reflect.Ptr { panic("FilterInPlace: wrong type, " + "not a pointer to slice") } _, n := filter(in.Elem().Interface(), function, true) in.Elem().SetLen(n) }
var boolType = reflect.ValueOf(true).Type()
funcfilter(slice, function interface{}, inPlace bool)(interface{}, int) {
sliceInType := reflect.ValueOf(slice) if sliceInType.Kind() != reflect.Slice { panic("filter: wrong type, not a slice") }
fn := reflect.ValueOf(function) elemType := sliceInType.Type().Elem() if !verifyFuncSignature(fn, elemType, boolType) { panic("filter: function must be of type func(" + elemType.String() + ") bool") }
var which []int for i := 0; i < sliceInType.Len(); i++ { if fn.Call([]reflect.Value{sliceInType.Index(i)})[0].Bool() { which = append(which, i) } }
out := sliceInType
if !inPlace { out = reflect.MakeSlice(sliceInType.Type(), len(which), len(which)) } for i := range which { out.Index(i).Set(sliceInType.Index(which[i])) }
//Container is a generic container, accepting anything. type Container []interface{}
//Put adds an element to the container. func(c *Container)Put(elem interface{}) { *c = append(*c, elem) } //Get gets an element from the container. func(c *Container)Get()interface{} { elem := (*c)[0] *c = (*c)[1:] return elem }