按值调用和按名称调用等价
Call-by-value and by-name equivalence
我正在参加 Coursera 的函数式编程课程,有时他们会讨论按值调用和按名称调用评估技术之间的区别。他们是让我感到困惑的一点,他们说:
Both techniques reduce to the same final values as long as:
- the reduced expressions consists of pure functions and
- both evaluations terminate
这似乎是一个 lambda 微积分定理。
你能解释一下 "the reduced expressions conssist of pure functions" 是什么意思吗?
纯函数是没有副作用的函数(例如执行 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
版本调用一次,保存结果并将其添加到自身。
对于纯函数,这完全没有区别 - 给定相同的参数,它总是 return 相同的结果,所以无论你调用它一次并使用保存的结果两次还是你调用它两次(性能除外)。
对于不纯的函数,它有很大的不同,因为每次调用函数时 sum
变量的值都会改变。
我正在参加 Coursera 的函数式编程课程,有时他们会讨论按值调用和按名称调用评估技术之间的区别。他们是让我感到困惑的一点,他们说:
Both techniques reduce to the same final values as long as:
- the reduced expressions consists of pure functions and
- both evaluations terminate
这似乎是一个 lambda 微积分定理。
你能解释一下 "the reduced expressions conssist of pure functions" 是什么意思吗?
纯函数是没有副作用的函数(例如执行 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
版本调用一次,保存结果并将其添加到自身。
对于纯函数,这完全没有区别 - 给定相同的参数,它总是 return 相同的结果,所以无论你调用它一次并使用保存的结果两次还是你调用它两次(性能除外)。
对于不纯的函数,它有很大的不同,因为每次调用函数时 sum
变量的值都会改变。