Has anyone written a formal paper describing a method to (automatically) convert functions to be tail recursive? I am looking for a university-level formal treatment including the limitations (types of functions that can be converted), procedures for conversion, and, if possible, proofs of correctness? Examples in Haskell would be a bonus.

- 137,316
- 36
- 365
- 468

- 31,584
- 38
- 145
- 282
-
I did some Googling, but could not find any specific references. I was hoping that someone could provide a reference or two. – Ralph May 22 '12 at 11:45
-
1A CPS transform would certainly do the job in the most generic case (and some consequent optimisations might eliminate most of the resulting cruft). Tons of papers are published on this topic. – SK-logic May 23 '12 at 10:15
2 Answers
a method to (automatically) convert functions to be tail recursive?
So there are two parts to this:
- recognizing that a given recursive function can be converted to a tail recursive form and making that transformation
- implementing tail calls in an efficient way, so the transformation is worth while.
Transforming recursion into tail recursion
It appears relatively straight forward to recognize tail recursive definitions syntactically. After all, 'tail recursive' just means that the call appears syntactically in the tail of the expression.
E.g. the Scheme folks describe:
merely compiling appropriate self-calls as jumps is not suficient to achieve full tail-recursion. Instead, we syntactically divide all sub-expression positions in the source language into two classes: tail (or reduction) position and subproblem position. In the simple expression (if
predicate
consequent alternative), thepredicate
is a subproblem position, while both consequent and alternative are in reduction positions. This syntactic notion can be easily extended to arbitrarily nested sub-expressions.
Transforming functions into tail calls
The tricky part of your question is optimizations for identifying and transforming candidate recursive computations into tail recursive ones.
One reference is in GHC, which uses inlining and a wide array of simplification rules to collapse away recursive calls, until their underlying tail recursive structure remains.
Tail Call Elimination
Once you have your functions in a tail-recursive form, you'd like to have that implemented effiicently. If you can generate a loop, that's a good start. If your target machine doesn't, then the tail call elimination" will need a few tricks. To quote Odersky and Schinz, cited below,
Various techniques have been proposed over the years to eliminate general (and not only recursive) tail calls, mostly for compilers targeting C.
... put the whole program in a big function and to simulate function calls using direct jumps or switch statements inside this function.
... A popular technique is to use a trampoline. A trampoline is an outer function which repeatedly calls an inner function. Each time the inner function wishes to tail call another function, it does not call it directly but simply returns its identity (e.g. as a closure) to the trampoline, which then does the call itself. Unlimited stack growth is thus avoided, but some performance is inevitably lost, mostly because all the calls made by the trampoline are calls to statically unknown functions.
Another technique is Henry Baker’s “Cheney on the M.T.A.” With his technique, the program first has to be converted to continuation passing style (CPS), therefore turning all calls into tail calls, and can then be compiled as usual. At run-time, when the stack is about to overflow, the current continuation is built and returned (or longjmped) to the trampoline “waiting” at the bottom of the call stack.
Tail call elimination on the Java Virtual Machine, Michel Schinz Martin Odersky, 2001
Henry G. Baker, Jr. CONS should not CONS its arguments, part II: Cheney on the M. T. A. Draft Version, January 1994.

- 137,316
- 36
- 365
- 468
-
I thought the OP was looking for a tail recursion elimination too, but the way the question is worded the OP seems to be looking for the opposite (or even a generalization of the opposite) -- quote: "convert functions to **be** tail recursive [emphasis mine]" – Attila May 22 '12 at 12:11
-
3The OP is asking about automatic conversion of recursive functions to tail-recursive form, in order to benefit from tail call elimination. He's not looking for tail call elimination itself. – Ben May 22 '12 at 12:52
-
The question is ambiguous. He isn't clear if he is looking for tail call elimination, or the tail recursion optimization in general. Either way, those papers are the place to start. – Don Stewart May 22 '12 at 12:59
-
2"a method to (automatically) convert functions to be tail recursive" seems pretty unambiguous to me. The mere fact that he's using the term "tail recursion" implies that he knows what tail-call elimination is, and that he asks for a university-level formal treatment suggests (although not conclusively) to me that he's not just accidentally misusing terms he doesn't fully understand. I may be wrong. – Ben May 22 '12 at 13:15
-
I've added sections on : identifying an expression with a recursive call in the tail position; GHC references for unfolding recursive calls to yield a tail call – Don Stewart May 22 '12 at 13:50
-
I'm actually looking for ways to convert general recursive functions to be tail recursive. I know how to do that in most cases using accumulators, but a set of rules that works in general, and can describe functions that **cannot** be converted would be nice. If I can convert most function to be tail recursive, the compiler will optimize the tail-recursive call to a **goto**, at least for GHC (I believe) and Scala. – Ralph May 22 '12 at 14:02
-
@Don Stewart: While investigating this, I found some implication that all functions can be converted to use CPS (continuation-passing style), and therefore consume heap instead of stack, but I could not find any formal "proof" of this. Thanks for the thorough answer. – Ralph May 22 '12 at 14:08
-
In "Real World Haskell" (http://shop.oreilly.com/product/9780596514983.do) the authors state that most imperative language compilers do **not** do tail-call elimination, and therefore even writing code in a tail-recursive manner will not see benefits. – Ralph May 22 '12 at 14:12
Mercury contains a couple of optimizations for automatically making things tail-recursive. (Mercury is an enforce-purity logic programming language, so it talks about predicates rather than functions, but many of the same ideas apply to Mercury programs as to Haskell ones. A much bigger difference than it being logical rather than functional is that it is strict rather than lazy)
"Accumulator introduction" generates specialised versions of predicates with an extra accumulator parameter in order to allow associative operations to be moved before the recursive call. Apparently this optimisation doesn't necessarily result in tail-recursive predicates on its own, but often results in a form which can be optimised by the second optimisation:
"Last call modulo constructors" essentially allows a recursive call that is followed only by constructor applications to be rewritten such that the value is constructed first containing a "hole" and then the recursive call returns its output directly into the memory address of the "hole" rather than using the normal return-value-passing convention. I believe Haskell would get this optimisation for free simply due to laziness, however.
Both of these optimisations are described in the paper Making Mercury programs tail recursive.

- 68,572
- 20
- 126
- 174