Tail Call Recursion in Java

on 2925-01-11

Last year I read a book called Functional Programming in Java by Venkat Subramaniam as I looked for inspiration for more complex uses of streams. One chapter stood out to me: tail call recursion. Handrolled bytecode can achieve TCO since javac doesn't support it (yet), so I was interested in what was going to be shown off.

TCO with handrolled factorial (bytecode reference):

 0: lload_0
 1: lconst_0
 2: lcmp
 3: ifne 8
 6: lload_2
 7: lreturn
 8: lload_0
 9: lconst_1
 10: lsub
 11: lload_0
 12: lload_2
 13: lmul
 14: lstore_2
 15: lstore_0
 16: goto

As mentioned, TCO isn't achievable with javac, but there are other methods to achieve similar outcomes (albeit with some overhead cost). I am referring to trampolining.

alt text

The key idea is that the recursive calls are turned into an iteration of TailCall<T> objects, and since streams are lazy, it fits very well!

I've seen recursion used frequently in production, where the worst outcome is possible, so this is a handy way of wrapping it up without major modification.

In my personal projects I've used it a lot when I'm trying to apply more 'functional' work to see how I feel about it (in Java), and I've thoroughly enjoyed it, perhaps more than writing imperative iterations, so I recommend you give it a go and seeing what you think!