Questions tagged «tail-call»

8
有哪些方法可以避免递归算法中的堆栈溢出?
题 解决由递归算法引起的堆栈溢出的可能方法是什么? 例 我正在尝试解决Project Euler问题14,并决定尝试使用递归算法。但是,该程序以java.lang.StackOverflowError停止。可以理解 该算法确实使堆栈溢出,因为我尝试为大量生成Collat​​z序列。 解决方案 所以我想知道:假设您的递归算法编写正确,并且最终会导致堆栈溢出,那么有什么标准方法可以解决堆栈溢出的问题呢?我想到了两个概念: 尾递归 迭代 想法(1)和(2)是否正确?还有其他选择吗? 编辑 最好查看一些代码,最好使用Java,C#,Groovy或Scala。 也许不要使用上面提到的Project Euler问题,这样它就不会被其他人宠坏,而是采用其他算法。阶乘可能,或类似的东西。

4
JVM对尾调用优化施加哪些限制
Clojure不会单独执行尾部调用优化:当您具有尾部递归函数并且想要对其进行优化时,必须使用特殊形式recur。同样,如果您有两个相互递归的函数,则只能使用来优化它们trampoline。 Scala编译器能够为递归函数执行TCO,但不能为两个相互递归函数执行TCO。 每当我阅读这些限制时,它们总是归因于JVM模型固有的某些限制。我对编译器一无所知,但这使我有些困惑。让我举一个例子Programming Scala。这里的功能 def approximate(guess: Double): Double = if (isGoodEnough(guess)) guess else approximate(improve(guess)) 被翻译成 0: aload_0 1: astore_3 2: aload_0 3: dload_1 4: invokevirtual #24; //Method isGoodEnough:(D)Z 7: ifeq 10: dload_1 11: dreturn 12: aload_0 13: dload_1 14: invokevirtual #27; //Method improve:(D)D 17: dstore_1 18: goto 2 因此,在字节码级别,只需要一个goto。实际上,在这种情况下,繁琐的工作由编译器完成。 基础虚拟机的什么功能将使编译器更轻松地处理TCO? …
36 scala  clojure  jvm  tail-call 

2
Y组合器和尾部调用优化
F#中Y组合器的定义是 let rec y f x = f (y f) x f希望将递归子问题的某些延续作为第一个论点。使用yf作为延续,我们可以看到f将应用于后续调用,因为我们可以开发 let y f x = f (y f) x = f (f (y f)) x = f (f (f (y f))) x etc... 问题是,先验的是,该方案无法使用任何尾部调用优化:的确,f中可能存在一些待处理的操作,在这种情况下,我们不能仅仅改变与f相关联的本地堆栈帧。 因此: 一方面,使用Y组合器需要一个与函数本身截然不同的延续。 在其他方面要应用TCO,我们希望f中没有待处理的操作,而仅调用f本身。 您知道这两者可以和解的任何方式吗?就像带累加器技巧的Y或CPS技巧的Y一样?还是有论据证明不可能做到这一点?

3
使用堆栈表示函数调用语义的替代方法有哪些?
我们都知道并喜欢函数调用通常是使用堆栈来实现的。有框架,返回地址,参数等等。 但是,堆栈是实现细节:调用约定可能会做不同的事情(例如,x86快速调用使用(某些)寄存器,MIPS和跟随器使用寄存器窗口,等等),优化甚至可以做其他事情(内联,帧指针省略,尾调用优化..)。 当然,许多机器(如JVM和CLR这样的VM,以及带有PUSH / POP等的x86等实际机器)上都存在方便的堆栈指令,可以很方便地将其用于函数调用,但是在某些情况下,这是可能的以不需要调用堆栈的方式进行编程(我在这里考虑的是Continuation Passing Style,或者消息传递系统中的Actor) 因此,我开始感到奇怪:是否可以在没有堆栈的情况下实现函数调用语义,或者更好地使用不同的数据结构(可能是队列,或者是关联映射?) ,当然,我知道堆栈非常有用。方便(它无处不在的一个原因),但是最近我碰到了一个使我感到奇怪的实现。 你们是否知道是否曾经用任何语言/机器/虚拟机完成过这项工作?如果有的话,有哪些显着的区别和缺点? 编辑:我的直觉是不同的子计算方法可以使用不同的数据结构。例如,lambda演算不是基于堆栈的(函数应用程序的想法通过简化来体现),但是我正在查看一种真实的语言/机器/示例。这就是为什么我要问...

4
没有TCO时,什么时候需要担心堆叠失败?
每次都针对以JVM为目标的新编程语言进行讨论,不可避免地会有人说: “ JVM不支持尾调用优化,因此我预计会有很多爆炸式堆栈” 该主题有成千上万的变体。 现在,我知道某些语言(例如Clojure)具有可以使用的特殊递归结构。 我不明白的是:缺少尾部呼叫优化有多严重?我什么时候应该担心呢? 我感到困惑的主要根源可能是因为Java是有史以来最成功的语言之一,而且相当多的JVM语言似乎运行得很好。这怎么可能,如果缺乏TCO的是真的任何关注?
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.