将scala中的函数调用作为参数传递,函数首先评估吗?

passing function calls in scala as arguments, does function evaluate first?

我只是在玩弄 Scala 中 foldlLeft 的实现

def foldLeft[A,B] (as: List[A], z: B) (f: (B, A) => B): B = as match {
  case Nil => z
  case Cons(x, xs) => foldLeft(xs, f(z,x)) (f)
}

在此实现中,f(z,x) 在作为 z 的参数给出的递归调用中,但我想知道这实际上是如何工作的? 当递归调用发生时,foldLeft()是接收f(z,b)执行的值还是按照写的方式接收函数调用,需要时再执行?

示例: 如果我们用以下值调用 foldLeft()

def foldLeft[A,B] ([1,2,3], 0) (f: (x, y) => x + y): B = as match {
  case Nil => z
  case Cons(x, xs) => foldLeft([2,3], f(0,1)) (f)
}

下一次执行foldLeft()会不会像这样,其中z等于f()的值?

def foldLeft[A,B] ([2,3], 1) (f: (x, y) => x + y): B = as match {
  case Nil => z
  case Cons(x, xs) => foldLeft([2,3], f(1,2)) (f)
}

还是像这样工作,foldLeft() 自己接电话?

def foldLeft[A,B] ([2,3], f(0,1)) (f: (x, y) => x + y): B = as match {
  case Nil => z
  case Cons(x, xs) => foldLeft([3], f(f(1,0),2)) (f)
}

问题本质上是关于何时评估尾递归函数的值?

Scala 与几乎所有主流语言一样,是一种 strict 语言,具有 eager 评估策略和 pass-by-value 参数传递语义。

这意味着all arguments to a method or function call will be fully evaluated before being passed into the method or function

然而,我写的实际上并不完全正确:那只是默认

有两种方法可以偏离默认:

  1. lazy modifier 创造价值,好吧,懒惰。
  2. by-name parameters 按名称传递,而不是按值传递。

#1 不适用于此处。 #2需要在参数列表中显式声明,这里不是这样。

因此,我们可以得出结论,是的,f(z, x) 将在对 foldLeft 的递归调用之前被完全评估。