编程范式
理解函数式程序的最大障碍之一是命令式程序背景下的思维转变。 命令式程序描述的是如何做某事,而声明式程序描述的是什么做什么。 让我们把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