一个懒惰的val可以尾递归吗?

时间:2014-08-18 13:11:40

标签: scala tail-recursion

lazy val seq: Unit = {
  println("a")
  seq
}

我们可以通过尾递归方式调用上面的表达式吗?

2 个答案:

答案 0 :(得分:2)

我想你可以在这个意义上辩解,是的 - 在评估时,seq会递归评估自己,而评估是最后一次执行的行动。

不管这是否可以被称为尾递归,但似乎没有太多意义。没有退出条件也没有,如果你尝试保持你的代码纯粹功能,可以有一个:没有参数,这意味着没有“状态”传递给更深层次的评估,没有任何东西可以测试以打破递归

此外,如果它确实是尾递归的,那么它不是Scala识别或支持的尾递归形式 - 评估seq并得到StackOverflowError

答案 1 :(得分:0)

您可以询问REPL:

scala> import scala.annotation.tailrec
import scala.annotation.tailrec

scala>   @tailrec
     |   def abc(a: Int): Int = a + abc(a+1)
<console>:10: error: could not optimize @tailrec annotated method abc: it contains a recursive call not in tail position
         def abc(a: Int): Int = a + abc(a+1)

scala>   @tailrec
     |   lazy val seq: Unit = {println("a"); seq}
seq: Unit = <lazy>

scala> seq
aa
a
...

(请原谅或更正某些命名错误)

据我所知,尾递归发生在你不需要上堆栈以获得前面的部分结果时,在我的例子中abc被递归调用,但你确实需要上去堆栈获取以前的结果(a + abc(a + 1)),如果它是abc(a+1)它将是一个尾递归函数:

scala>   @tailrec
     |   def abc(a: Int): Int = abc(a+1)
abc: (a: Int)Int

scala> abc(0)
  ...

您的val定义不需要上堆,因为没有操作需要与堆叠期间累积的部分结果相结合。