package main import ( "fmt" "reflect" ) type duck interface{} // Python like map function func Map(fn duck, list duck) duck { fnType, fnValue := reflect.TypeOf(fn), reflect.ValueOf(fn) listValue := reflect.ValueOf(list) // fmt.Println("assert", fnType.NumOut() == 1, fnType.NumIn() == 1, fnType.In(0) == listType.Elem()) rtnType := reflect.SliceOf(fnType.Out(0)) rtnValue := reflect.MakeSlice(rtnType, 0, listValue.Len()) for i := 0; i < listValue.Len(); i++ { in := []reflect.Value{listValue.Index(i)} rtnValue = reflect.Append(rtnValue, fnValue.Call(in)[0]) } return rtnValue.Interface() } // Python like range function func Range(n int) []int { rtn := make([]int, 0, n) for i := 0; i < n; i++ { rtn = append(rtn, i) } return rtn } type in chan duck // Python like list comprehension construction func List(fn func(x in)) duck { x := make(chan duck) go func() { fn(x); close(x) }() first := <-x rtnType := reflect.SliceOf(reflect.TypeOf(first)) rtnValue := reflect.MakeSlice(rtnType, 0, 0) rtnValue = reflect.Append(rtnValue, reflect.ValueOf(first)) for v := range x { rtnValue = reflect.Append(rtnValue, reflect.ValueOf(v)) } return rtnValue.Interface() } func main() { fn := func(x int) string { return fmt.Sprintf("%dx%d=%d", x, x, x*x) } // Compare to rtn = map(fn, range(10)) rtn := Map(fn, Range(10)).([]string) fmt.Println(rtn) // Compare to rtn2 = [ i * i for i in range(5)] rtn2 := List(func(x in) {for i := 0; i < 5; i++ { x <- i * i }}).([]int) fmt.Println(rtn2) }