编程范式
理解函数式程序的最大障碍之一是命令式程序背景下的思维转变。 命令式程序描述的是如何做某事,而声明式程序描述的是什么做什么。 让我们把1到10的数字相加来说明这一点。
命令式
#![allow(unused)] fn main() { let mut sum = 0; for i in 1..11 { sum += i; } println!("{}", sum); }
对于命令式程序,我们必须模拟编译器来看看发生了什么。
在这里,我们从一个值为0的sum开始。
接下来,我们在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的一个惯例。
在这里,我们正在组成加法的函数(闭包:|a, b| a + b),范围是从1到10。
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 |
Latest commit 2cd70a5 on 22 Jan 2021