什么是纯函数?
在函数式编程里我们会经常谈到这两个概念。一个是 纯函数。另一个是 附加作用。这里我们就结合实际来介绍一下 纯函数 和 附加作用。
下面我们给出两个函数 increaseA
和 increaseB
,他们其中一个是 纯函数,另一个不是 纯函数:
var state = 0
func increaseA() {
state += 1
}
increaseA()
print(state) // 结果: 1
func increaseB(state: Int) -> Int {
return state + 1
}
let state = increaseB(state: 0)
print(state) // 结果: 1
他们的作用差不多,使 state + 1
, 我们可以猜测一下 increaseA
和 increaseB
哪一个是 纯函数
...
...
...
... 经过 10 秒后
现在公布答案:increaseB
是 纯函数,increaseA
不是 纯函数
为什么 increaseB
是 纯函数
因为他特别 纯洁:除了用入参 state
计算返回值以外没做任何其他的事情。
那为什么 increaseA
不是 纯函数
因为他修改了函数本体以外的值 state
, 他拥有这个 附加作用,因此他 并不纯洁 就不是 纯函数
我们再来做以下两个测试,然后猜测他们能不能测试成功:
func testIncreaseA() {
increaseA()
state == 1 // 结果:?? 🤔
}
func testIncreaseB() {
let state = increaseB(state: 0)
state == 1 // 结果:true 😎
}
...
...
...
... 经过 20 秒后
嗯... 这里我们可以肯定第二个测试 testIncreaseB
会成功。0 + 1
肯定等于 1
。那第一个测试呢?这可不好说了,我们并不知道 increaseA
是在什么环境下被调用的,不知道在这个环境下初始 state
是多少。如果他是 0
那测试就会成功的,如果他不是 0
那测试就会失败的。因此在不知道所处环境时,我们无法判断测试是否会成功。
由于 increaseA
存在修改外部 state
的 附加作用 所以他不是 纯函数。事实上如果函数有以下任意一种作用,他也不是纯函数:
- 发起网络请求
- 刷新 UI
- 读写数据库
- 获取位置信息
- 使用蓝牙模块
- 打印输出
- ...
我们将这些作用称为函数的 附加作用(副作用)。
而 纯函数 的定义就是: 1.没有 附加作用 的函数,2.并且在参数相同时,返回值也一定相同。
因此在已知执行逻辑时,纯函数 所产生的结果是可以被预测的。一些现代化的库都利用了这个特性来做状态管理,如:RxFeedback, Redux,ReactorKit 等等。
什么是函数的附加作用?
如果一个函数除了计算返回值以外,还有其他可观测作用,我们就称这个函数拥有 附加作用
网友评论