Go Programming Languages - Functional Programming
Functional Programming in GO: Closure (闭包)
1 | import "fmt" |
闭包与Python类似,里面有函数体,函数体里有局部变量和自由变量(e.g.,
sum
)。
对应的Python闭包方式 1
2
3
4
5
6
7
8
9def adder():
sum = 0
def f(value):
nonlocal sum
sum += value
return sum
return fnonlocal
就是标准,表示该变量不是局部变量
缺点
但是 Go 中的函数式编程因为不像Python一样不用限制类型(泛型的缺失,duck typing),就会导致后续代码会很难维护
比如 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18func main() {
var list = []string{"Orange", "Apple", "Banana", "Grape"}
// we are passing the array and a function as arguments to mapForEach method.
var out = mapForEach(list, func(it string) int {
return len(it)
})
fmt.Println(out) // [6, 5, 6, 5]
}
// The higher-order-function takes an array and a function as arguments
func mapForEach(arr []string, fn func(it string) int) []int {
var newArray = []int{}
for _, it := range arr {
// We are executing the method passed
newArray = append(newArray, fn(it))
}
return newArray
}map[int]
,那不就得开发一个
1
2
3
4
5
6
7
8func mapInt64ForEach(arr []int64, fn func(it int64) int) []int {
var newArray = []int{}
for _, it := range arr {
// We are executing the method passed
newArray = append(newArray, fn(it))
}
return newArray
}
采用高阶函数的递归
借用 fibonacci 的实现我们简单地示例返回一个函数的方式来实现递归:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22package main
import "fmt"
func fibonacci() func() int {
a, b := 0, 1
return func() int {
a, b = b, a+b
return a
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
// 依次输出:1 1 2 3 5 8 13 21 34 55
延迟计算 Delayed Calculating
使用高阶/匿名函数的一个重要用途是捕俘变量和延迟计算,也即所谓的惰性计算(Lazy evaluations)
1 | func doSth(){ |
在 defer
的高阶函数中,捕俘了外部作用域中的
err
变量,doSth 的整个运行周期中对 err
的设定,最终能够在 defer
函数体中被正确计算得到。如果没有捕俘和延迟计算机制的话,高阶函数体中对
err
的访问就只会得到 nil
值,因为这是捕俘时刻
err
的具体值。换句话说,在高阶函数中对外部作用域的访问是动态地延迟地计算的。
Go Programming Languages - Functional Programming