编程范式
当出于一个命令式的背景时,理解函数式程序最大的障碍之一就是思维的转变。命令式程序说明了如何做,然而声明式程序说明做了什么。让我们用对1到10求和的例子来说明这一点。
命令式
#![allow(unused)] fn main() { let mut sum = 0; for i in 1..11 { sum += i; } println!("{}", sum); }
在命令式程序中,我们必须用编译器来查看发生了什么。这里sum
起始为0,然后我们在1到10范围内循环,每次循环中我们加上对应的值,最后输出。
i | sum |
---|---|
1 | 1 |
2 | 3 |
3 | 6 |
4 | 10 |
5 | 15 |
6 | 21 |
7 | 28 |
8 | 36 |
9 | 45 |
10 | 55 |
这就是我们大多数人开始编程的方式。我们了解到程序是一些操作步骤的集合。
声明式
#![allow(unused)] fn main() { println!("{}", (1..11).fold(0, |a, b| a + b)); }
哇哦!这真是不一样!这里发生了啥?记住声明式程序说明了做了什么,而不是如何去做。fold
是一个 组合函数的函数。这个名字来自于Haskell。
这里,我们组合了在1到10范围内的加法函数(闭包|a,b| a + b
)。0
是起始点,所以a
最开始是0
,b
是范围的第一个元素1
。结果是
0 + 1 = 1
。所以现在我们再次fold
,a = 1
、b = 2
下一个结果是1 + 2 = 3
。这个过程一直持续到范围内最后一个元素10
。
a | b | result |
---|---|---|
0 | 1 | 1 |
1 | 2 | 3 |
3 | 3 | 6 |
6 | 4 | 10 |
10 | 5 | 15 |
15 | 6 | 21 |
21 | 7 | 28 |
28 | 8 | 36 |
36 | 9 | 45 |
45 | 10 | 55 |