在scala中将函数调用作为参数传递,函数是否首先求值?

在scala中将函数调用作为参数传递,函数是否首先求值?,scala,recursion,tail-recursion,Scala,Recursion,Tail Recursion,我只是在玩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)的值,或

我只是在玩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()
的值

或者它是这样工作的,
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与几乎所有主流语言一样,是一种严格的语言,具有急切求值策略和按值传递参数的语义

这意味着

然而,我所写的事实并不完全正确:这只是默认情况

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

  • 这使得一个价值,嗯,懒惰
  • 按名称传递,而不是按值传递
  • #1在这里不适用#2需要在参数列表中显式声明,这里不是这种情况

    因此,我们可以得出结论,是的,
    f(z,x)
    将在对
    foldLeft

    z
    的递归调用是类型B之前被完全计算,因此您只能传递B,不能传递函数,不能传递按名称参数,不能传递其他任何东西;只是一个普通的B。另外,
    f(z,x)
    是对函数的一种求值,它将在生成B之前被执行(记住Scala是一种渴望的语言,而不是像Haskell那样懒惰的语言)。
    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)
    }