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