vlambda博客
学习文章列表

函数式编程(三):纯函数的重要性


前一篇文章中,我们讨论了函数式编程语言中最重要的特性:一等公民。在本文中,我们将讨论纯函数,每一个函数式编程概念都以此为基础。

1.什么是纯函数

简洁地说,纯函数是一种确定性函数,不会产生副作用。

2.纯函数的特征

2.1 特征1:️纯函数必须是确定性的

确定性函数,是一个函数,对于相同的输入x输出应该总是相同的y。
一些不确定函数的例子:
Math.random

const random = () => Math.random()
  • Date函数
const getDate = () => Date.now()
  • getUsers
const getUsers = await fetch('/users')

这些例子是不确定性函数,因为对于相同的输入,输出将不同。(注意:getUsers函数是不确定的,因为用户可能已更新,没有internet连接,或者服务器可能已关闭,或者其他原因)
总结:决定性意味着一个函数永远不会在同一个输入上改变输出。

2.2特征2:纯功能必须没有副作用

副作用可能是:

  • 外部依赖性(访问外部变量、I/O流、读取/写入文件或进行http调用)。
  • 改变(局部/外部变量或传递的引用参数上的改变)。是的,纯函数应该是确定性的,不应该产生任何类型的副作用。同时,有状态的应用程序不可能没有副作用(查询数据库、执行http调用、读取用户输入,甚至在UI上显示结果)。但别担心,函数式编程有一些解决方案。
    关于副作用的例子:

isLessThanMin

有副作用(非纯函数):

let min = 60
const isLessThanMin = value => value < min

纯函数:

const isLessThanMin = (min, value) => value > min

为什么不是纯函数?外部依赖 解决方案:依赖注入

squares

有副作用(非纯函数):

const squares = (nums) => {
    for(let i = 0; i <nums.length; i++) nums[i] **=2;
}

纯函数

const squares = (nums) => nums.map(num => num * num)

为什么不是纯函数?在原始数组上进行改变的命令式代码。解决方案:使用map函数代替。这会创建一个新数组

updateUserAge
非纯函数:

const updateUserAge = (user, age) => {
    user.age = age
}

纯函数

const updateUserAge = (user, age) => ({ ...user, age }) 

为什么不是纯函数,更改用户传递的引用数据。解决方案:不要改变用户的传递引用数据,而是返回一个新对象

getFirst2Elements

有副作用(非纯函数):

const getFirst2Elements = (arr) => arr.splice(02)

纯函数:

const getFirst2Elements = (arr) => arr.slice(02)

为什么不是纯函数?在传入的arr变量上使用 splice,改变数组的状态。解决方案:使用slice 方法,不改变数组状态的切片方法

3.为什么非纯函数不好

在研究了非纯函数的例子之后,可以得到一些明显的缺点:

  • 使功能与环境紧密结合
  • 增加开发者的认知负荷
  • 诱导状态假设
  • 增加开发人员的代码库学习曲线
  • 并发的超级敌人
  • 高度不可预测性 其中,每一个缺陷可能部分是另一个缺陷的结果。

4.为什么纯函数是好的

根据纯函数规则,我们有两大类进步。开发者体验和应用程序性能:

  • 在开发者体验方面(DX):考虑到我们的函数现在是确定性的、独立的和自包含的。在以下方面将有明显的改进:
  1. 可预测性:消除外部因素和环境变化将使函数更加健全和可预测。
  2. 可维护性:可预测的函数更容易推理。这将减少状态假设和开发人员的认知负荷。
  3. 可组合性:函数独立,仅通过输入和输出进行通信,这将使我们能够轻松组合函数。
  4. 可测试性:函数的自我约束和独立性将提升可测试性。
  • 在应用程序性能方面:
  1. 缓存能力:函数的确定性使我们能够通过输入预测输出(因为每个输入都有一个不变的输出),然后我们可以基于输入缓存函数。
  2. 并行化能力:由于功能现在无副作用且独立,因此可以轻松地进行并行化。

5.   4096核 CPU

我们生活在一个多核机器的时代。如今,普通的CPU都有8个核心,每个核cpu都在争抢计算机的资源。如果我们的软件不能在它们之间进行协调,那么所有这些cpu都将毫无用处。

正如bob所问:
在4096个处理器争夺资源的情况下,您将如何编写可靠的代码?答案在于纯函数。纯函数不会产生副作用,因此不会出现并发问题。所以函数式编程是未来。它将毫无压力的处理一个4096核CPU的并发性。

6.结论

纯函数是函数式编程的核心。它们遵从一套规则。遵从这些规则将产生巨大的收益,这将引领计算机的未来。

译自:https://blog.bitsrc.io/functional-programming-part-2-pure-functions-85491f3d7190

                                                         少爷,点个关注和在看呗!