Many noob Lispers, including myself, have a hard time understanding, what is proper tail call/recursion/optimization, and what is not. Here is some code I've stole from Wikipedia. (Rewritten to pure C.)
#include <stdio.h>
int fact_iter(int n, int a)
{
if (n==0)
return a;
return fact_iter(n-1, n*a);
};
int fact(int n)
{
return fact_iter(n, 1);
};
void main()
{
printf ("%d\n", fact(11));
};
So far, this is a recursive version of factorial. How can we optimize it? Remove recursion? Here is how (pure C again):
...
int fact_iter(int n, int a)
{
begin:
if (n==0)
return a;
// modify arguments.
// as if this function called again with new arguments:
a=n*a;
n=n-1;
goto begin;
};
...
Ugly? "Go To Statement Considered Harmful"? Yes. A rare case, when function argument's modification is justified. But if the end of your function can be rewritten so manually, a Lisp compiler would be able to do this as well. This is what happens in low-level.
To write a tail-recursive function, think, if you can rewrite it in such a way.
On contrary, this function can't be rewritten (again, copy-pasted from Wikipedia), so a Lisp compiler couldn't optimize it (Python code):
def fact(n):
if n == 0:
return 1
else:
return n * fact(n - 1)
Aside from Lisp, ML dialects (OCaml, etc), Haskell also supports tail calls. But Python is not.

Yes, I know about these lousy Disqus ads. Please use adblocker. I would consider to subscribe to 'pro' version of Disqus if the signal/noise ratio in comments would be good enough.