按值调用和按名称等效

时间:2016-09-29 14:35:42

标签: scala functional-programming lambda-calculus callbyname call-by-value

我参加了关于函数式编程的Coursera课程,并且在某些时候他们讨论了按值调用和按名称调用评估技术之间的区别。他们说,他们有点困惑我,他们说:

  

只要符合以下条件,这两种技术都会降低到相同的最终值:

     
      
  1. 简化表达式由纯函数和
  2. 组成   
  3. 两个评估终止
  4.   

这似乎是一个lambda演算定理。

你能解释一下他们的意思吗?"简化的表达对于纯粹的功能和#34;?

1 个答案:

答案 0 :(得分:4)

纯函数是没有副作用的函数(例如执行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变量的值。