【问题标题】:scala tail recursion decorator not letting tail recursive function to be calledscala尾递归装饰器不允许调用尾递归函数
【发布时间】:2019-05-08 14:32:51
【问题描述】:
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 是自包含的,可以在不引用调用堆栈的情况下进行迭代。

【问题讨论】:

  • 你为什么要对一个可选项进行尾递归?
  • 因为最终返回值是可选的。返回类型与尾递归有何关系? @DamianLattenero 我使用递归的主要原因是因为 try catch 块。这些不是功能构造。通过将异常的概念封装到 Option Monad 中,我实质上是将程序函数转换为函数函数。
  • 不需要递归:funcs.toStream.flatMap(f => util.Try(f()).toOption).headOption

标签: scala recursion tail-recursion


【解决方案1】:

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

无论如何,我还建议您避免使用 Seq 进行尾递归算法(您应该改用 Listtry / catch(使用 @ 987654325@ 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 }
}

【讨论】:

  • 不知道 try monad。好的答案谢谢。一个附带的问题......为什么使用列表而不是 Seq 进行尾递归算法?
  • 一般来说Seq应该避免,因为当你有一个Seq你真的不知道你有什么。因此,您执行的任何操作都可能不安全或性能不佳,this 以更详细的方式解释了该问题。 - 现在,特别是对于 tail-recursive 算法。人们通常以 head-tail 方式遍历集合,这对Lists 有意义,因为其中包含 O(1)。但是,如果您有 ArrayVector,那么 tail 将是 O(N),因为它必须将所有数据复制到新集合中。
【解决方案2】:

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

 FuncUtils.tryAll(funcs.tail: _*)

应该是:

 tryAll(funcs.tail: _*)

当我引用库时,我猜 scala 无法弄清楚它是递归的。

【讨论】:

    猜你喜欢
    • 2018-03-17
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多