我正在参加有关函数式编程的 Coursera 课程,并且在某些时候他们讨论了按值调用和按名称调用评估技术之间的区别。他们有些让我困惑,他们说:
两种技术都减少到相同的最终值,只要:
- 简化的表达式由纯函数和
- 两个评估都终止
这似乎是一个 lambda 演算定理。
你能解释一下“简化的表达式由纯函数组成”是什么意思吗?
我正在参加有关函数式编程的 Coursera 课程,并且在某些时候他们讨论了按值调用和按名称调用评估技术之间的区别。他们有些让我困惑,他们说:
两种技术都减少到相同的最终值,只要:
- 简化的表达式由纯函数和
- 两个评估都终止
这似乎是一个 lambda 演算定理。
你能解释一下“简化的表达式由纯函数组成”是什么意思吗?
纯函数是没有副作用的函数(例如执行 IO 或更改任何非函数本地的值)。纯函数的一个例子是:
def inc(x: Int) = x+1
一个不纯函数的例子是:
var sum = 1
def addToSum(x: Int) = {
sum += x
sum
}
因此,现在让我们考虑以下两种方法,它们的区别仅在于它们是按名称还是按值获取参数:
def doubleByValue(x: Int) = x + x
def doubleByName(x: =>Int) = x + x
现在,如果我们将这两者与纯函数一起使用,结果是相同的:
doubleByValue(inc(2)) // => 6
doubleByName(inc(2)) // => 6
但如果我们将它们应用于不纯函数,结果会有所不同:
sum = 1 // Let's reset sum, so the result isn't affected by previous uses
doubleByValue(addToSum(2)) // => 6, the value of `sum` is now 3
sum = 1 // Let's reset sum, so the result isn't affected by previous uses
doubleByName(addToSum(2)) // => 8, the value of `sum` is now 5
不同之处在于ByName
版本调用该函数两次并添加两个结果,而ByValue
版本调用它一次,保存结果并将其添加到自身。
对于纯函数,这完全没有区别 - 给定相同的参数,它总是返回相同的结果,因此无论是调用一次并使用保存的结果两次还是调用两次(性能除外)都没有区别。
对于不纯函数,它会产生很大的不同,因为sum
每次调用函数时都会更改变量的值。