【问题标题】:How usable is non tail recursive recursion in Scala?Scala 中的非尾递归递归有多有用?
【发布时间】:2014-07-08 19:49:33
【问题描述】:

由于非尾递归递归调用像 Java 一样使用堆栈帧,我会厌倦做任何递归,比如说超过 1,000 次。因此,我会厌倦将它用于大多数事情。

人们真的在 Scala 中使用非尾递归递归吗?如果是这样,我可以使用什么标准来确定它是否可以是非尾递归的?

此外,是否有计划在未来版本的 Scala 中移除此内存限制?

【问题讨论】:

  • 在很多情况下,关于域的事实意味着堆栈上的递归不太可能成为问题。以 UI 菜单树为例——如果它的深度足以溢出堆栈,那么无论如何你的程序都会出现更严重的问题。
  • “另外,有没有计划在未来版本的 Scala 中移除这个内存限制?”这不是语言版本问题。如果您编写的调用不是尾调用(递归或非递归),则将需要一个堆栈帧(以保持状态以在非尾调用返回后继续计算)。 Java 和大多数其他语言也是如此。
  • @Paul:然而,即使 JVM 仍然有大量可用堆,您也很容易用完堆栈,这是当前实现的产物,对吧?至少在理论上,Scala 编译器可以编译调用,使其使用堆而不是堆栈来保持状态?
  • 是的,这就是我说“大多数语言”的原因。有一些语言可以做到这一点(例如方案和呼叫/抄送,我相信),但开销很大。我们一直使用堆栈而不是堆的原因是分配和释放的效率。不过,我看不到 Scala(或任何主流语言)对正常调用的性能造成影响以允许无限递归。
  • 这里几乎相同的问题:stackoverflow.com/questions/24619987/…

标签: scala recursion tail-recursion


【解决方案1】:

在您不能使用单尾递归的情况下,例如因为您需要在两个函数之间进行选择,已经描述了一种称为trampolining 的机制。

可以在 Rúnar Bjarnason 的论文 Stackless Scala With Free Monads 中找到有关此主题的最新和全面讨论。

就个人而言,如果你真的遇到这种深度 >1K 的情况,我会走简单的路线并恢复为命令式风格,例如使用可变集合构建器。

【讨论】:

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