Tail Call optimisation

Tail call optimisation is compiler based optimisation ,it is used to avoid allocating new stack space in case of recursive call in function.So let’s see what happens in tail call optimisation. When a function is called, the computer must “remember” the place it was called from, the return address, but in case of tail call the new called function is not alloted with a new stack space instead it replaces the the calling function in the same stack due to which stack overflow can be avoided.Most of the funtional program support tail call optimisation.For function having tail call optimisation it should have the proper implementation. Let’s see by example how to write tail call optimisation:

( define ( fact x ) ( if ( = x 0 ) 1 ( * x ( fact ( - x 1 )))))

Above implementation of factorial doesn’t do tail call optimisation because when the recursive call is made, the function needs to keep track of the multiplication it needs to do with the result after the call returns.

( fact 3 ) (* 3 ( fact 2 )) (* 3 (* 2 ( fact 1 ))) (* 3 (* 2 (* 1 ( fact 0 )))) (* 3 (* 2 (* 1 1 ))) (* 3 (* 2 1 )) (* 3 2 ) 6

So tail call implementation of factorial will be as follows:

( define ( fact x ) ( define ( fact-tail x accum ) ( if ( = x 0 ) accum ( fact-tail ( - x 1 ) ( * x accum )))) ( fact-tail x 1 ))

It’s stack trace will be :

( fact 3 ) ( fact - tail 3 1 ) ( fact - tail 2 3 ) ( fact - tail 1 6 ) ( fact - tail 0 6 ) 6

As you can see that every call of function is completely independent of it’s previous information.This means that even if we were to call (fact 1000000), we need only the same amount of space as (fact 3) because the new function will replace the previous function call in the stack thereby reducing stack overflow.This is not the case with the non-tail-recursive fact, and as such large values may cause a stack overflow.

Some of the language like scheme,haskell support tail call optimisation but languages like java,python doesn’t support it.We’ll see in future blog why does these languages doesn’t support tail-call optimisation.