这是我参与[第五届青训营]的第十一天。
函数式编程(functional programming)是一种编程设计模范(paradigm)。主要思想见于lisp和ml家族的编程语言。函数式编程易于平行处理。大数据框架Hadoop和Spark的思想,也基于函数式编程。
函数式编程的基本前提是函数为一级对象,即认为函数也是值,可以作为参数也可以作为返回值。
package main
import (
"fmt"
)
func main() {
f := func() {
fmt.Println("Hellow World")
}
f()
}
在上面的例子中,定义了一个函数对象f,并调用它。
高阶函数
也可以将函数对象作为另一个函数的参数,这种函数成为高阶函数(higher-order function)。
package main
import (
"fmt"
)
func apply(arr []float64, callback func(float64) float64) []float64 {
out := make([]float64, len(arr))
for i, e := range arr {
out[i] = callback(e)
}
return out
}
func main() {
arr := []float64{1, 2, 3, 4, 5}
// Square
sqr := apply(arr, func(n float64) float64 {
return n * n
})
fmt.Println(sqr)
// Cubic
cub := apply(arr, func(n float64) float64 {
return n * n * n
})
fmt.Println(cub)
// Inverse
inv := apply(arr, func(n float64) float64 {
return 1.0 / n
})
fmt.Println(inv)
}
在上例中,对同一个函数apply传入不同的函数,得到了不同的结果。
闭包
函数对象除了作为参数,也可以做为回传值。
package main
import (
"log"
)
func run() func() int {
n := -1
return func() int {
n += 1
return n
}
}
func main() {
f := num()
if !(f() == 0) {
log.Fatal("Wrong number")
}
if !(f() == 1) {
log.Fatal("Wrong number")
}
if !(f() == 2) {
log.Fatal("Wrong number")
}
}
在上例中,每次调用函数f,得到的数值会递增1,这种带有状态的函数,称为闭包(closure)
严格计算 和 惰性计算
主流的编程语言大多都是严格计算。 以下的go惰性计算是错误的:
package main
import (
"fmt"
)
func main() {
fmt.Println(len([]int{1, 2, 3 / 0, 4}))
}
这里一提,Haskell语言的上述表示是正确的,因为Haskell语言是惰性计算的特性。
main = print len
list = [1, 2, 3/0, 4]
len = length list
递归
递归不是函数式程序设计专有的特性,然而,函数式编程语言中支持尾部调用优化(tail-call optimization),使得递归和控制结构达到相近的速度,在go中没有实现这样的特性。