可以函数tail-recursive

时间:2014-09-02 03:34:37

标签: function scala tail-recursion

我有一些递归代码我想重构使用来自Enumerator的尾递归,我可以简化递归看起来像这样,请忽略此功能想要实现的功能。

@tailrec
def doStuff: List[Int] => Int = {
      case Nil => 0
      case x :: xs => doStuff(xs)
    }

如果我摆脱了tailrec注释,它工作正常,结构看起来像这个doStuff(doStuff(doStuff(..)))。它将有stackoverflow异常。

那么如果它是一个函数

,我怎么能使它递归递归

3 个答案:

答案 0 :(得分:5)

匿名函数不能进行尾递归。让我们首先对代码进行非常简单的重写,以引入val来保存结果函数。

@tailrec
def doStuff: List[Int] => Int = {
  val result: List[Int] => Int = {
    case Nil => 0
    case x :: xs => doStuff(xs)
  }
  result
}

从那里开始,应该很清楚doStuff(xs) 调用匿名函数本身。它调用方法doStuff返回您要调用的函数。更糟糕的是,因为它是def,它实际上会在每次调用时返回不同的函数。因此,匿名函数绝对不会调用本身

问题归结为这个简单的事实:匿名函数是匿名的。因此,他们无法直接称呼自己:他们总是会调用可能会自行返回的其他defval,但编译器并不知道这一点。

出于这个原因,只有@dhg提出的def正确的theMethod _才真正是尾递归的。

现在,如果你真的想要返回一个函数值,这恰好是用尾递归的情况实现的,你可以简单地使用val doStuff = { @tailrec def rec(list: List[Int]): Int = list match { case Nil => 0 case x :: xs => rec(xs) } rec _ } 将方法转换为函数。因此,您的初始问题的解决方案如下:

rec

请注意,我们声明了一个正确的尾递归方法rec _),然后我们将其转换为{{1}}的函数值。

答案 1 :(得分:1)

可能你的意思是这个?

@tailrec
def doStuff(list: List[Int]): Int = list match {
  case Nil => 0
  case x :: xs => doStuff(xs)
}

答案 2 :(得分:0)

  

那么如果它是一个函数

,我怎么能使它递归递归

你不能。我的意思是,当然你可以在Scala中编写一个尾递归函数,但它不会帮助你,因为它不会得到优化。

Scala只优化直接尾递归方法调用。