Go 1.1 達到類似 Python 的 map 及 list comprehension
Posted by tjwei on 星期四, 4月 25, 2013 with No comments
Go 1.1 的 reflect 新增了 SliceOf, ChanOf,以及 MakeFunc。
SliceOf 及 ChanOf 可以達到類似於 Python 裡面的 list 及 iterator 的功能,MakeFunc 可以搭配 Call 使用,達到類似 decorator 的功能。
以下是簡單測試了一下 Python 的 map 及類似 list comprehension 的效果。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
0 意見:
張貼留言