编程技巧:函数式补充语法
>= 1.0.13-sp13
函数式编程是种编程方式,它将电脑运算视为函数的计算。 函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。 和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。 和过程化编程相比,函数式编程里函数的计算可随时调用。
yak 支持一定程度的函数式编程语法。例如 Map/Filter/Reducer
等操作。
但是这些操作的支持并不是集成在全局函数中,而是由一个特殊的包来引入的。
x.Map
基础函数式编程:映射#
如果我们需要对一个集合进行变换,在 Python 中,我们可以使用 for
的 inline 语句,但是在 yak 中,我们通过 x
模块应用函数式中常用的 "Map" 功能。
例如我们要对一个整数列表全体 +1 可执行如下代码
dump(x.Map([1,2,3,4,5], func(i){return i+1}))
执行结果为
([]interface {}) (len=5 cap=8) { (int) 2, (int) 3, (int) 4, (int) 5, (int) 6}
x.Map
代替普通的 for 循环批处理#
使用 我们阅读一段代码,他的意思是,把一个数组集合中的内容经过 MD5 计算,获得一个新的数组
传统的写法为
origin = [ "127.0.0.1:123", "127.0.0.1:1231", "127.0.0.1:1233", "127.0.0.1:1234", "127.0.0.1:1235",]
after = []for _, i = range origin { after = append(after, codec.Md5(i))}dump(after)
如果使用函数式,就会非常简单
origin = [ "127.0.0.1:123", "127.0.0.1:1231", "127.0.0.1:1233", "127.0.0.1:1234", "127.0.0.1:1235",]
after2 = x.Map(origin, func(i){return codec.Md5(i)}) // 函数式调用dump(after2)
当然,这两段代码的执行结果完全一致:
([]interface {}) (len=5 cap=8) { (string) (len=32) "9c6cd8a653b32a49024e548ee9d333c2", (string) (len=32) "57e14469d056f261d1e29e25187ad3c1", (string) (len=32) "8f72b71f93052f9b8659d3c4b5aecec3", (string) (len=32) "93454abf54cf365c703f8e3c695562bf", (string) (len=32) "9373bd92a6686d67baed2873188e7e68"}
x.Filter
代替 for 循环筛选#
使用 还是上面的代码,我们稍微对其进行一点变种,我们过滤出以 :1233
或者 :1234
结尾的字符串
origin = [ "127.0.0.1:123", "127.0.0.1:1231", "127.0.0.1:1233", "127.0.0.1:1234", "127.0.0.1:1235",]
after = []for _, line = range origin { if str.MatchAnyOfGlob(line, "*:1233", "*:1234") { after = append(after, line) }}dump(after)
在这种情况下,x.Filter
可以起到很好的作用。
after = x.Filter(origin, func(i){return str.MatchAnyOfGlob(i, "*:1233", "*:1234")})dump(after)
note
当然 x.Map 与 x.Filter 是完全可以混用的!
我们可以先过滤,再联合进行额外处理例如
x.Map(x.Filter([1,2,3,4,5], func(i){return i > 3}), func(i){return i + 10})
计算结果应该为 [14, 15]
x.Find
代替 for 循环寻找关键元素#
使用 我们修改上面的代码,让它变成 "遇到符合要求的值就返回" 以找到我们想要的值
origin = [ "127.0.0.1:123", "127.0.0.1:1231", "127.0.0.1:1233", "127.0.0.1:1234", "127.0.0.1:1235",]
findResult = func() { for _, line = range origin { if str.MatchAnyOfGlob(line, "*:1233", "*:1234") { return line } } return ""}dump(findResult())
同样的,我们在 x.Find
中可以很轻易实现这个操作
dump(x.Find(origin, func(i){return str.MatchAnyOfGlob(i, "*:1233", "*:1234")}))
上面两段代码的执行结果都为
(string) (len=14) "127.0.0.1:1233"
x.Reducer
求列表和#
经典案例:result = x.Reduce([1,2,3,4,5,6,7,8], func(a,b){return a+b}, 0)println(result) // 36