Scala @tailrec带折叠

mop*_*pot 1 recursion scala fold

scala的@tailrec注释是否支持Option.fold方法?

@tailrec
def test(a: Int): Int =
  if (a > 10)
    Option(true).fold(test(a - 1))(_ => test(a - 2))
  else
    -1
Run Code Online (Sandbox Code Playgroud)

此代码导致错误:

无法优化@tailrec带注释的方法测试:它包含一个不在尾部位置的递归调用

这个问题可以通过模式匹配来解决,但我觉得fold看起来更干净.

Pet*_*ens 9

当你想在Scala中编写一个尾递归函数时,你对尾递归函数的调用需要在最后一个位置(因此尾调用递归).

在你的情况下Option.fold是最后一个,Scala编译器无法弄清楚结果fold始终是一个调用test.

您可以使用TailCals,使用以下命令编写尾递归函数fold:

import scala.util.control.TailCalls._

def test(a: Int): TailRec[Int] =
  if (a > 10) tailcall(Option(true).fold(test(a - 1))(_ => test(a - 2))) 
  else done(-1)

test(11).result // -1
Run Code Online (Sandbox Code Playgroud)

如果您发现TailRec使用模式匹配比使用模式匹配更简洁,那么您需要:

def test(a: Int): Int =
  if (a > 10) Option(true) match {
    case Some(_) => test(a - 2)
    case None => test(a - 1)
  }
  else -1
Run Code Online (Sandbox Code Playgroud)