文章目录
1、函数式编程
1.1 函数与闭包
经典样例
func adder() func (value int) int{
sum := 0
return func(value int) int{
sum += value
return sum
}
}
func main(){
adder := adder()
for i := 0; i < 10; i++{
fmt.Println(adder(i))
}
}
1.2 函数式编程 VS 函数指针
- 函数是一等公民:参数、变量、返回值都可以是函数
- 高阶函数
- 函数 --> 闭包
1.2.1 “正统”函数式编程
- 不可变性:不能有状态,只有常量和函数
- 函数只能有一个参数
将样例改为“正统”函数式编程
type iAdder func(int) (int, iAdder)
func adder2(base int) iAdder{
return func(v int) (int, iAdder){
return base+v, adder2(base+v)
}
}
func main(){
a := adder2(0)
for i := 0; i < 10; i++{
var s int
s, a = a(i)
fmt.Println(s)
}
}
1.2.2 闭包
这里的局部变量相当于v,而自由变量是返回函数之外的,也就是sum是一个自由变量。
1.2.2.1 python中的闭包
def adder():
sum = 0
def f(value):
nonlocal sum
sum += value
return sum
return f
- python是原生支持闭包的
- 使用___course___来查看闭包内容
1.2.2.2 c++中的闭包
// c++14
auto adder(){
auto sum = 0;
return [=] (int value) mutable{
sum += value;
return sum;
}
}
- 过去:stl或者boost都有类似库
- c++11及以后:支持闭包
1.2.2.3 java中的闭包
Function<Integer, Integer> adder(){
final Holder<Integer> sum = new Holder<>(0);
return (Integer value) -> {
sum.value += value;
return sum.value;
};
}
- java1.8以后:使用Function接口和Lambda表达式来创建函数对象
- java中函数不是一等公民,所以没有办法作为参数,变量等。
- 匿名类或者Lambda表达式均支持闭包
函数式编程样例一
2.1 斐波那契数列
package main
import "fmt"
func fibonacci() func() int{
var fib1 = int(0)
var fib2 = int(1)
return func() int{
fib1, fib2 = fib2, fib1+fib2
return fib1
}
}
func main(){
f := fibonacci()
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
}
2.2 为函数实现接口
package main
import (
"bufio"
"fmt"
"io"
"strings"
)
type intGen func() int
func fibonacci() intGen {
var fib1 = int(0)
var fib2 = int(1)
return func() int{
fib1, fib2 = fib2, fib1+fib2
return fib1
}
}
func (g intGen) Read(p []byte) (n int, err error) {
next := g()
if next > 10000 {
return 0, io.EOF
}
s := fmt.Sprintf("%d\n", next)
return strings.NewReader(s).Read(p)
}
func printFibonacci(reader io.Reader){
scanner := bufio.NewScanner(reader)
for scanner.Scan(){
fmt.Println(scanner.Text())
}
}
func main(){
f := fibonacci()
printFibonacci(f)
}
2.3 使用函数遍历二叉树
package main
import (
"fmt"
)
type Node struct{
Value int
Left, Right *Node
}
func (node *Node) Print(){
fmt.Print(node.Value, " ")
}
func (node *Node) Traverse(){
node.TraverseFunc(func (n *Node) {
n.Print()
})
fmt.Print()
}
func (node *Node) TraverseFunc(f func(*Node)) {
if node == nil{
return
}
node.Left.Traverse()
f(node)
node.Right.Traverse()
}
func main(){
var root = new(Node)
root.Value = 0
root.Left = &Node{2, nil, nil}
root.Right = &Node{3, nil, nil}
root.Left.Right = &Node{4, nil, nil}
root.Right.Left = &Node{5, nil, nil}
root.Traverse()
nodeCount := 0
root.TraverseFunc(func(node *Node){
nodeCount++
})
fmt.Println("Node count=", nodeCount)
}
2.4 go语言闭包的应用
- 更为自然,不需要修饰如何访问自由变量
- 没有Lambda表达式,但是有匿名函数