Scala尾部递归装饰器不允许调用尾部递归函数

时间:2019-05-07 21:57:22

标签: scala recursion tail-recursion

object FuncUtils {
  @tailrec
  def tryAll[T](funcs: (() => Any)*): Option[Any] = {
    if (funcs.isEmpty) {
      None
    } else {
      try {
        Some(funcs.head())
      } catch {
        case _: Throwable => FuncUtils.tryAll(funcs.tail: _*)
      }
    }
  }
}

为什么?在我看来,tryAll是自包含的,并且可以在不引用调用堆栈的情况下进行迭代。

2 个答案:

答案 0 :(得分:3)

该错误无法重现,您可以尝试提供更多上下文。

无论如何,我还建议您避免使用Seq进行尾部递归算法(您应改用List)和try / catch块< em>(改为使用Try Monad)
这是使用它重写的代码。

import scala.util.{Try, Success, Failure}

object FuncUtils {
  def tryAll[T](funcs: (() => T)*): Option[T] = {
    @annotation.tailrec
    def loop(remaining: List[() => T]): Option[T] = remaining match {
      case Nil     => None
      case x :: xs => Try(x()) match {
        case Success(t) => Some(t)
        case Failure(_) => loop(remaining = xs)
      }
    }

    loop(remaining = funcs.toList)
  }
}

再次,如jwvh所说,在这种情况下,您确实不需要递归。

object FuncUtils {
  def tryAll[T](funcs: (() => T)*): Option[T] =
    funcs.iterator.map(f => Try(f())).collectFirst { case Success(t) => t }
}

答案 1 :(得分:0)

好的原因是因为在调用函数之前,我是指方法包含在其中的Singleton对象。

 FuncUtils.tryAll(funcs.tail: _*)

应该是:

 tryAll(funcs.tail: _*)

我想当我引用库时,scala不能弄清楚它的递归性。