【问题标题】:Order of execution of functions in functional programming函数式编程中函数的执行顺序
【发布时间】:2015-10-03 05:16:15
【问题描述】:
从过去 6 个月开始,我开始学习函数式编程的概念。
在阅读许多资料时,我发现其中一件事是在函数式编程中,执行顺序是未定义的!这个我不是很清楚。
从另一个 Stack Overflow 答案:https://stackoverflow.com/a/23290/1276021,“功能语言”(理想情况下)允许您编写“数学函数”。
但是,就像在数学函数中一样,f(g(x)) !== g(f(x)) - 意思是执行顺序很重要。
似乎我理解“执行顺序未定义”的概念是错误的。我哪里错了?
【问题讨论】:
标签:
javascript
functional-programming
【解决方案1】:
f(g(x)) !== g(f(x)) - 含义,执行顺序问题。
不,那些是不同的表达式/程序,不仅仅是不同的执行顺序。
似乎我对“执行顺序未定义”的概念理解错误
正确的、更详细的语句应该是“表达式各部分的evaluation 的顺序无关”(并且总是会导致相同的结果)。这意味着这样的函数式语言没有 side effects 和 referential transparency - 这两个非常重要的属性用于证明“数学”函数也具有。
如果我们定义两个函数
f(x) = x*3
g(y) = y+1
然后尝试评估表达式f(g(1)),不管我们是否先做
f(g(1))
= f(1+1)
= f(2)
= 2*3
= 6
或
f(g(1))
= g(1)*3
= (1+1)*3
= 2*3
= 6
无论我们先应用哪个函数,我们总是会到达 6。
【解决方案2】:
是的,执行顺序由编译器决定,而对程序员来说,这并不重要。
但是每个函数的输入是什么很重要:
- f(g(x)) 表示用g(x)的结果调用f的结果
- g(f(x)) 表示用 f(x) 的结果调用 g 的结果
考虑这个例子:
a(b(x)) + b(x) + c(b(x))
编译器将决定首先计算b(x) 的结果,然后在a 和c 函数调用中使用该结果。但是一个优化得很差的编译器可能会决定找出b(x),然后调用a,然后再次找出b(x),然后再找出c(b(x))。最终,他们都会得出相同的答案,因此就程序员而言,执行顺序无关紧要。大多数情况下,编写良好的编译器会比使用命令式语言手动计算出的最佳执行顺序远远,尤其是当事情变得复杂时,因此最好不要考虑执行顺序,而不是将其作为实现细节留给编译器解决。
【解决方案3】:
在函数式编程中,就像在数学中一样,函数是作为参数的有效值。
取这两个函数
f(x) = x ^ 2
g(x) = 2x - 4
采取以下作文f(g(x))。如果我们先评估f:
F = f(g(x)) = (g(x)) ^ 2
我们的新F 在数学中仍然是一个有效的函数,就像在函数式编程中一样。
然后,如果我们将 g(x) 评估为 g(3),我们会得到:
g(3) = 2 * 3 - 4 = 2
然后我们可以评估F
F = (2) ^ 2 = 4
评估的顺序无关紧要。