如果我们在算法中使用循环而不是递归,反之亦然,那么两者是否可以起到同样的作用?例如:检查给定的字符串是否为回文.我已经看到许多程序员使用递归作为一种手段来展示一个简单的迭代算法可以适应账单.编译器在决定使用什么方面起着至关重要的作用吗?
我问这个问题是为了了解如何在JVM中增加运行时调用堆栈的大小.我已经得到了答案,我还得到了许多有用的答案和评论,这些答案和评论与Java如何处理需要大型运行时堆栈的情况有关.我已经用答案摘要扩展了我的问题.
最初我想增加JVM堆栈大小,所以程序就像没有运行的程序一样StackOverflowError.
public class TT {
public static long fact(int n) {
return n < 2 ? 1 : n * fact(n - 1);
}
public static void main(String[] args) {
System.out.println(fact(1 << 15));
}
}
Run Code Online (Sandbox Code Playgroud)
相应的配置设置是java -Xss...具有足够大值的命令行标志.对于TT上面的程序,它与OpenJDK的JVM一样:
$ javac TT.java
$ java -Xss4m TT
Run Code Online (Sandbox Code Playgroud)
其中一个答案还指出,这些-X...标志是依赖于实现的.我在用
java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8.1) (6b18-1.8.1-0ubuntu1~8.04.3)
OpenJDK 64-Bit Server VM (build 16.0-b13, mixed mode)
Run Code Online (Sandbox Code Playgroud)
也可以仅为一个线程指定一个大堆栈(参见其中一个答案如何).建议使用此方法java -Xss...以避免为不需要它的线程浪费内存.
我很好奇上面的程序需要多大的堆栈,所以我运行它n增加了:
fact(1 …在jvm-prevent-tail-call-optimization之后两年,似乎有一个原型 实现,MLVM已经将该功能列为"proto 80%"一段时间了.
Sun的/ Oracle方面是否没有积极的兴趣支持尾调用,或者只是尾部调用" 在每个功能优先级列表中排在第二位 [...]"如JVM所述语言峰会?
如果有人测试了MLVM构建并且可以分享它的工作原理(如果有的话),我会非常感兴趣.
更新: 请注意,像Avian这样的某些虚拟机支持正确的尾部调用,没有任何问题.
java language-agnostic optimization jvm tail-call-optimization
可能重复:
为什么JVM仍然不支持尾调用优化?
我在网上看到了很多不同的答案,所以我想我会问专家.
我是一名主要使用C++的科学家,但我希望找到更好的语言.我正在寻找建议,我甚至不确定我的"梦想语言"是否存在,但这是我的愿望清单;
重要特征 (按重要性排序)
1.1:表现:对于科学,表现非常重要.我完全理解生产力的重要性,而不仅仅是执行速度,但是当你的程序必须运行几个小时时,你就无法用Python或Ruby编写它.它不需要像C++一样快,但它必须相当接近(例如:Fortran,Java,C#,OCaml ......).
1.2:高水平和优雅:我希望能够尽可能地集中精力学习科学并获得清晰的代码.我也不喜欢像Java那样的冗长语言.
1.3:功能完备:我喜欢函数式编程,我认为它非常适合我的风格和科学编程.我不在乎语言是否支持命令式编程,它可能是一个优点,但它必须集中并鼓励函数式编程.
1.4:可移植性:应该在Linux(特别是Linux!),Mac和Windows上运行良好.不,我不认为F#在单声道Linux上运行良好,我不确定OCaml在windows上运行良好;)
1.5:面向对象,最好是在"一切都是对象"的哲学下:我意识到在不久前我不得不处理纯C的时候,我更喜欢面向对象的编程.我喜欢对面向对象编程有强烈承诺的语言,而不仅仅是胆小的支持.
不是很重要,但是那些事情会很好
2.1:"不太强"的打字:我发现Haskell强大的打字系统很烦人,我喜欢能够做一些隐式转换.
2.2:工具:好的工具总是有利的,但我想这实际上取决于语言.我使用轻量级编辑Geany与Haskell一起玩,我从未感到残疾.另一方面,我不会用Java甚至Scala做同样的事情(特别是Scala似乎缺乏好的工具,这实在是太遗憾了).Java在这里确实是第一语言,使用NetBeans和Javadoc,使用Java编程非常简单有趣.
2.3:收集垃圾,但在没有虚拟机的情况下进行翻译或编译.我没有反对虚拟机,但域中的两个巨头都有他们的问题.在纸面上,.net框架看起来好多了,特别适合函数式编程,但在实践中它仍然以Windows为中心,对Linux/MacOS的支持很糟糕,并不是应该的,所以它并不值得考虑.Java现在是一个成熟的虚拟机,但它在某些层面上让我很烦恼:我不喜欢它处理可执行文件,泛型的方式,并且它编写了可怕的GUI(虽然这些东西并不是那么糟糕).
我尝试在网上挖掘以解答我的问题.我找到了一些与达芬奇项目有关的文件.这被标记为JSR 292,它与在JVM中包含闭包有关.这个项目是否实现了,它是Java 8的一部分吗?
是否有一种功能语言可以提供良好的支持和工具来构建Web服务?我一直在研究Scala(它编译为JVM并可以使用Java库)和F#(这是.NET),但这些都是年轻的并且效率低下.特别是Scala不支持尾调用消除,除了自递归函数,这限制了你可以做的组合种类(这是JVM的一个基本限制).F#是非常新的,似乎还没有得到完全支持,这使它比传统语言更具风险.
是否可以使用Haskell,ML或任何其他更传统的函数语言构建Web服务,或者最好是使用Scala还是F#?还有其他建议吗?
标题很好地反映了我的问题.我想知道有关JVM(不仅仅是HotSpot,但显然是开始的地方)如何实现或处理特定功能的问题是否有良好的资源或跳跃点?我不是在寻找JLS或JVM规范中的东西- 我知道先去那里.
例如:在尝试理解性能问题时,我们经常进行的对话不是关于规范的内容,而是实际实现中的当代最佳实践.例如,有一些城市神话说"最终类在Java中表现更好,因为JVM可以内联或以其他方式优化这些东西." 是否有一般资源我们可以转向以评估这些浮动的声明?
我通过HotSpot特定的参考资料回答了我自己的问题.其他供应商的产品呢?小型JVM的细节?多核细节?平台细节,如果它们有所作为?其他JVM语言的细节?
只是为了避免一些潜在的抱怨:1)这不是寻找过早的优化(事实上,更好地理解平台应该劝阻受过良好教育的开发人员!); 2)我知道Java程序员应该专注于漂亮,可移植,随处运行的代码,但对于我们中的许多人而言,平台细节最终会引起关注!
这是通过对一些有用的意见启发的具体问题由托尔比约恩Ravn的安德森.我很高兴收集一些其他更有用的例子,超出我上面引用的例子,以激发人们可能想要这些资源的原因.
在SO一些有趣的相关问题:尾部调用优化的JVM,杀手JVM功能,优化,都将是无用的明天,JVM实现之间的差异.
编辑添加: 我将答案提供给所提及的最佳个人参考,或者提供指向网站的指针(可能是为了回答这个问题而建立的),最好地集中/编目JVM实施智慧和实际后果.客户语言和开发人员.
通过搜索此站点和Web上的其他位置,JVM不支持尾调用优化.因此,这是否意味着如果要在JVM上运行,则不应写入可能在非常大的输入列表上运行的尾递归Scala代码(如下所示)?
// Get the nth element in a list
def nth[T](n : Int, list : List[T]) : T = list match {
case Nil => throw new IllegalArgumentException
case _ if n == 0 => throw new IllegalArgumentException
case _ :: tail if n == 1 => list.head
case _ :: tail => nth(n - 1, tail)
}
Run Code Online (Sandbox Code Playgroud)
Martin Odersky的Scala示例包含以下段落,似乎表明存在适合递归的情况或其他环境:
原则上,尾调用总是可以重用调用函数的堆栈帧.但是,某些运行时环境(例如Java VM)缺少基本条件,以使堆栈帧重用用于尾调用.因此,生产质量Scala实现只需要重新使用直接尾递归函数的堆栈帧,其最后一个操作是对自身的调用.其他尾调用也可以进行优化,但不应该在实现中依赖于此.
任何人都能解释一下这段中间两句话是什么意思吗?
谢谢!
我正在研究Tail调用递归,并且遇到了一些提到的文档.Sun Java没有实现尾调用优化.我写了以下代码以3种不同的方式计算斐波纳契数:1.迭代2.头递归3.尾递归
public class Fibonacci {
public static void main(String[] args) throws InterruptedException {
int n = Integer.parseInt(args[0]);
System.out.println("\n Value of n : " + n);
System.out.println("\n Using Iteration : ");
long l1 = System.nanoTime();
fibonacciIterative(n);
long l2 = System.nanoTime();
System.out.println("iterative time = " + (l2 - l1));
System.out.println(fibonacciIterative(n));
System.out.println("\n Using Tail recursion : ");
long l3 = System.nanoTime();
fibonacciTail(n);
long l4 = System.nanoTime();
System.out.println("Tail recursive time = " + (l4 - l3));
System.out.println(fibonacciTail(n));
System.out.println("\n Using Recursion : ");
long …Run Code Online (Sandbox Code Playgroud) java ×6
jvm ×3
optimization ×3
recursion ×3
scala ×2
algorithm ×1
f# ×1
fibonacci ×1
java-8 ×1
performance ×1
stack ×1
tail ×1
web-services ×1