【问题标题】:Tail recursion optimization and recursion in JavaJava中的尾递归优化和递归
【发布时间】:2015-02-23 09:43:31
【问题描述】:

我有一个关于尾调用优化的问题,我需要知道这段 java 代码的行为方式:

private void doSomething(int v) {

    inf f = someCalculation(v);

    if (f < 0) doSomething(v/2);
    else doSomething(v*2);

}

这段代码是一个无意义的例子,但我的问题是,在这种情况下:

  1. 第一个 doSomething() 调用会被优化吗?
  2. 第二个 doSomething() 调用会被优化吗?
  3. if/else 块以任何方式影响优化?

谢谢

编辑:

请提供一个示例,说明如果语言不是 Java 而是其他具有 TCO 的语言,您将如何做到这一点

【问题讨论】:

  • 最后两行可以改写为doSomething((f &lt; 0) ? (v/2) : (v*2));...
  • 那么您的问题到底出在哪里?共有三个问题,请尝试提供答案。
  • 首先:优化几乎从不保证。当代码“及时”优化时,可以优化的事实并不意味着它会优化,尤其是在 Java 中。
  • @GiulioFranco 尾调用优化是一个定义明确的概念,确定性(和静态)应用于支持它的语言。事实上,它是如此普遍,以至于支持它的语言可以称为“TCO 语言”。
  • @MarkoTopolnik 所有(或许多)优化都是一个定义明确的概念。通常不容易做的是确定这个概念是否适用于我们编写的代码。如果某些语言标准化了 tco 适用且必须应用的条件,那我不知道。

标签: java recursion tail-call-optimization tail-call


【解决方案1】:

Java 8 没有任何尾调用优化。不会优化任何调用(变成迭代/goto 语句)。

不过,关于 Java 的 TCO 的讨论由来已久,Guy Steele 是其最著名的支持者之一。

我建议阅读mlvm-dev 邮件列表中的this post,以了解有关该主题的最新评论。

【讨论】:

  • 我读到 Java 8 有某种 TCO,但我真的无法理解,因为有人说它有,另一些人说没有……所以最终的答案是,根本没有 TCO?
  • HotSpot 的 JIT 编译器中可能也许有什么东西(不过我个人从未听说过),但 Java 规范中肯定没有。所以,既然你没有任何保证某个习语不会破坏堆栈,那将没有什么用处。
  • java 12 怎么样?
【解决方案2】:

尝试运行以下代码:

public static void main(String[] args) {
  for (int i = 1; i > 0; i *= 2) { doSomething(i); }
}

private static void doSomething(int start) {
  doSomething(start, start);
}

private static void doSomething(int i, int start) {
  if (i == 0) { System.out.println("done from " + start); }
  else { doSomething(i - 1, start); }
}

如果 JVM 可以在没有堆栈溢出的情况下运行它,那么这应该意味着它可以进行尾递归优化(或非常好的常量传播)。

【讨论】:

  • AFAIK TCO 如果尾调用是最后一条指令,那么如果我有类似“return doSomething()”之类的东西作为最后一条指令会发生什么? return 语句是否算作最后一条指令,因此无法完成 TCO?
  • return doSomething() 是可优化尾调用的典型示例。更重要的是doSomething(),因为 TCO 的主要用例是递归纯函数,根据定义,它们绝不是void
猜你喜欢
  • 2014-06-23
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-14
  • 2012-11-15
  • 2011-09-04
相关资源
最近更新 更多