编程范式
当出于一个命令式的背景时,理解函数式程序最大的障碍之一就是思维的转变。命令式程序说明了如何做,然而声明式程序说明做了什么。让我们用对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 |