[1] http://stackoverflow.com/questions/105834/does-the-jvm-preve...
[1] http://stackoverflow.com/questions/105834/does-the-jvm-preve...
The JVM security model allows a function to goto anywhere inside the current function, but does not allow a goto to outside the current function.
This means that JVM based languages can do tail call optimizations in self-recursive functions, but can't TCO in mutually recursive functions.
With Clojure, Rich Hickey thought there was some accidental complexity here, so he added the recur special form. Recur guarantees the call is in the tail position, and throws an exception if it isnt. Recur can go to the top of the function, or an enclosing loop block inside the function.
To do mutual recursion in Clojure, you use a trampoline. That looks like
(declare even? odd?)
(defn even? [x]
(if (= x 0)
true
#(odd? (dec x)))
(defn odd? [x]
(if (= x 1)
true
#(even? (dec x)))
(trampoline even? 100)
What we're doing here is defining two mutually recursive functions, but instead of calling the other directly, we return a function of no arguments that calls the other function. Then call trampoline, passing the function and any arguments. Not the most elegant solution, but it works.Please bear with me as I'm not familiar with Lisp family languages. I'm interested in ML languages. There is a project to port OCaml to JVM, but I don't see any sign of progress, so I thought it may be something on JVM to hold them back.
OCaml on the JVM would have the same problems, if not worse. Eliminating tail recursion is essential in the ML family, and doing that while sanely supporting Java interop seems to be difficult.
I don't really keep up with it much, but I remember proposals to give some bytecode operations that would help here in the next Java version. Not sure if any of them made it past that stage.