为什么scala编译器没有标记看似不是尾部递归函数的函数?

为什么scala编译器没有标记看似不是尾部递归函数的函数?,scala,tail-recursion,Scala,Tail Recursion,我已经标记了sameLength方法来检查和优化尾部递归。我觉得SameleLength方法中的最后一个操作不是SameleLength。是&。&&在else子句中。为什么编译器不标记这个。由于编译器没有标记它,我假设它确实是尾部递归的。有人能为我定义尾部递归吗?我脑子里的定义是错误的 import scala.annotation.tailrec object TestTailRec extends App{ @tailrec def sameLength[T](

我已经标记了sameLength方法来检查和优化尾部递归。我觉得SameleLength方法中的最后一个操作不是SameleLength。是&。&&在else子句中。为什么编译器不标记这个。由于编译器没有标记它,我假设它确实是尾部递归的。有人能为我定义尾部递归吗?我脑子里的定义是错误的

  import scala.annotation.tailrec


  object TestTailRec extends App{

    @tailrec
    def sameLength[T](xs: List[T], ys: List[T]) : Boolean = {
      if(xs.isEmpty) ys.isEmpty
      else ys.nonEmpty && sameLength(xs.tail, ys.tail)
    }

    println(sameLength(List(1,2,3), List(1,2,3)))

  }

让我们稍微重构一下您的方法,而不改变其含义:

def sameLength[T](xs: List[T], ys: List[T]) : Boolean = {
  if(xs.isEmpty) ys.isEmpty
  else if (ys.isEmpty) false else
  sameLength(xs.tail, ys.tail)
}
我想现在很清楚了,这是尾部递归

定义了
布尔
&
方法

由于
Boolean
是一个值类,因此
if/else
表达式是内联的

由于
p
参数是按名称计算的,因此不首先计算它

严格的版本证实了你的直觉:

scala> @tailrec def f(i: Int): Boolean = false & f(i)
<console>:16: error: could not optimize @tailrec annotated method f: it contains a recursive call not in tail position
scala>@tailrec def f(i:Int):Boolean=false&f(i)
:16:错误:无法优化@tailrec注释的方法f:它包含一个不在尾部位置的递归调用

我不知道编译器是否会这样做,但布尔表达式是通过“短路”方法计算的:如果ys.nonEmpty为false,则无需计算SameleLength。如果它是真的,那么它将返回sameLength的结果,使其确实是尾部递归的