我知道纯函数属于“函数式编程”范式,您创建一个没有任何副作用的函数,并且对于输入它总是返回相同的输出,例如:
function (a,b) {
return a + b;
}
这是一个纯函数,因为对于输入我总是返回相同的输出并且我没有产生任何副作用。好的,我明白了。
但是当我真正想要创建一个副作用时,我如何才能制作“纯函数”,我如何才能留在“函数式编程”范例中,例如更改 DOM 中的文本内容,例如:
function changeContent () {
let content = document.querySelector("#content");
content.textContent = 'Hello World';
}
这个函数有副作用,它不是获取输入并返回输出,而是产生副作用,但这实际上是函数的重点。这还是“函数式编程”吗?在那种情况下如何保持“函数式编程”范式?
最佳答案
How can I stay in the "functional programming" paradigm when I actually want to create a side effect?
你真的不能。纯函数不得有任何副作用。
当然,这意味着我们实际上无法将执行任何操作的程序建模为纯函数。有两种解决方法:
牺牲纯洁。只需编写一个具有副作用的函数即可。彻底记录下来,以便每个使用该功能的人都知道这一点。对程序的命令部分进行不同的推理。
这是大多数编程语言的首选解决方案,因为它们不强制要求纯度,而且您经常可以摆脱它。
构建一个(纯)数据结构,明确描述您希望程序具有的效果。然后有一个不纯的“解释器”来执行它们来“运行”你的程序。 (我不会在这里详细介绍这种数据结构如何工作,有不同的方法,解释会超出问题的范围)。
在 Haskell 中,它强制所有函数的纯度,这个数据结构是
IO
类型,它基本上描述了命令式计算,并且它的解释器内置在运行时中。
在同样保证纯度的 Elm 中,有 Elm architecture在浏览器中使用 Web API 和 DOM 进行建模,并且在编译为 JS 时每个程序都需要一个小的运行时。
在 JavaScript 中,没有这样的解释器。您可以自己构建一个(或使用为此目的构建的库),但最终您必须在程序中的某处调用它的 run
函数,这会将您带回到#1。
特别是对于 DOM:描述文档更改的数据结构相对容易构建。您甚至可以引入纯功能优化,例如将避免多次写入同一位置,或写入随后无论如何都会被删除的位置。
但是,DOM 是 JavaScript 异步特性的基础部分。很难描述与多事件输入和输出的潜在并发交互。
关于javascript - 当您真正想要产生副作用时, "functional programming"背后的哲学是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50568722/