Scala 为什么不是';函数尾部不是递归的吗?

Scala 为什么不是';函数尾部不是递归的吗?,scala,recursion,tail-recursion,Scala,Recursion,Tail Recursion,我正在读m.Odersky的Scala编程,他说 函数,例如近似函数,它们将自己称为最后一个函数 动作,称为尾部递归 所以,我试过这个: object Main extends App { implicit val mc = new MyClass(8) val ti = new TestImplct ti.test } class TestImplct { def test(implicit mc : MyClass): Unit = { println(

我正在读m.Odersky的Scala编程,他说

函数,例如近似函数,它们将自己称为最后一个函数 动作,称为尾部递归

所以,我试过这个:

object Main extends App {
    implicit val mc = new MyClass(8)
    val ti = new TestImplct
    ti.test
}

class TestImplct {
  def test(implicit mc : MyClass): Unit = {
    println(mc.i)
    mc.i -= 1
    if(mc.i < 0){
      throw new IllegalArgumentException
    }
    test
  }
}

class MyClass(var i : Int)
这意味着它为每个递归调用生成一个新的堆栈帧。但最后的行动是呼吁自己。出了什么问题以及如何使其返回


为什么编译器不进行尾部调用优化?

您可以尝试使用
@tailrec
注释标记该方法。若您这样做,编译将失败,并将向您展示为什么编译器无法将其优化为尾部递归:

Main.scala:12:错误:无法优化@tailrec注释的方法测试:它既不是私有的,也不是最终的,因此可以重写


事实上,如果您将方法设置为final,它将按预期工作。

您的代码工作正常。
mc
对象中的值会随着每一步而减少。在最后一步,您将得到异常

例如,您可以将函数的返回类型更改为
Boolean
,当值为
<0
时返回
false
,否则返回
true


我建议您使用'@tailrec'注释,以便编译器检查递归函数调用。

您在作用域中有MyClass的隐式实例吗?@Samar是的,我有。看看演示,我看你已经定义了这个类。但我看不出你在哪里实例化了它。@Samar啊,你说得对。我没有;不要附上完整的代码。我的同事们,很好用。你为什么认为它不是尾部递归的?它只是因为if条件而退出。有趣。为什么在这里使方法最终允许TCO?@Samar+1也想知道。正如错误所说:否则方法可能会被一些不是尾部递归的实现覆盖,那么您可能会认为您看到的是尾部递归,而实际上并非所有调用都能进行此优化。
 Exception in thread "main" java.lang.IllegalArgumentException
    at TestImplct.test(Main.scala:13)
    at TestImplct.test(Main.scala:15)
    at TestImplct.test(Main.scala:15)
    at TestImplct.test(Main.scala:15)
    at TestImplct.test(Main.scala:15)
    at TestImplct.test(Main.scala:15)
    at TestImplct.test(Main.scala:15)
    at TestImplct.test(Main.scala:15)
    at TestImplct.test(Main.scala:15)