1

I have a question about tail calls optimization, I need to know how this java code behaves:

private void doSomething(int v) {

    inf f = someCalculation(v);

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

}

This code is a nonsense example but my question is, in such a case:

  1. The first doSomething() call would be optimized?
  2. The second doSomething() call would be optimized?
  3. The if/else block affects in any way the optimization?

Thanks

EDIT:

Please provide an example on how you would do this if the language was not Java but something else that has TCO

Francesco Rigoni
  • 923
  • 7
  • 20
  • The last two lines can be rewritten as `doSomething((f < 0) ? (v/2) : (v*2));`... – Oliver Charlesworth Feb 23 '15 at 09:46
  • So where is exactly your problem? There are three questions, try to provide an answer. – Kiril Feb 23 '15 at 09:46
  • First of all: optimization is *almost never* a guarantee. The fact something can be optimized doesn't mean it will, particularly in Java, when code is optimized "just in time". – Giulio Franco Feb 23 '15 at 10:01
  • @GiulioFranco Tail call optimization is a well-defined concept, deterministically (and statically) applied in languages which support it. It is so pervasive, in fact, that a language supporting it can be referred to as a "TCO'd language". – Marko Topolnik Feb 23 '15 at 10:13
  • @MarkoTopolnik all (or many) optimizations are a well defined concept. What's often not easy to do is to determine if the concept is applicable to the code we write or not. If some language standardizes conditions where tco is applicable and must be applied, that I don't know. – Giulio Franco Feb 23 '15 at 10:16
  • Yes, they certainly do formalize it, and code idioms depend on its reliable application. Clojure uses a trick to achieve something similar: `(recur)`, which fails at compile time if it occurs at a non-tail position. Scala has the `@tailrec` annotation with similar effect. – Marko Topolnik Feb 23 '15 at 10:18

2 Answers2

5

Java 8 has no Tail Call Optimization whatsoever. No calls will be optimized (turned into iteration/goto statements).

The discussion over TCO for Java has a long history, though, with Guy Steele being one of its best-known proponents.

I recommend reading this post from the mlvm-dev mailing list for a recent review of the subject.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • I read that Java 8 has some kind of TCO, but I really cannot understand because someone says it has, some other say no.... so final answer is, there's no TCO at all? – Francesco Rigoni Feb 23 '15 at 09:57
  • 1
    There may *perhaps* be something in HotSpot's JIT compiler (never heard of it personally, though), but there is definitely nothing in the specification of Java. So, since you don't have any *guarantee* that a certain idiom will not blow the stack, that would be of little use. – Marko Topolnik Feb 23 '15 at 10:07
  • what about java 12? – ses Jun 29 '19 at 21:28
0

Try running the following code:

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); }
}

If the JVM can run it without stack overflow, then it should mean it can do tail recursion optimization (or a very good constant propagation).

Giulio Franco
  • 3,170
  • 15
  • 18
  • AFAIK TCO can be done if the tail call is the very last instruction, so what happens if I have something like "return doSomething()" as the last instruction? does the return statement count as the last instruction so no TCO can be done? – Francesco Rigoni Feb 23 '15 at 10:17
  • `return doSomething()` is the quintessential example of an optimizable tail call. Much more so that just `doSomething()` because TCO's primary use case are recursive *pure functions*, which are by definition never `void`. – Marko Topolnik Feb 23 '15 at 10:26