Very simply, what is tail-call optimization?
More specifically, what are some small code snippets where it could be applied, and where not, with an explanation of wh
Probably the best high level description I have found for tail calls, recursive tail calls and tail call optimization is the blog post
"What the heck is: A tail call"
by Dan Sugalski. On tail call optimization he writes:
Consider, for a moment, this simple function:
sub foo (int a) { a += 15; return bar(a); }So, what can you, or rather your language compiler, do? Well, what it can do is turn code of the form
return somefunc();into the low-level sequencepop stack frame; goto somefunc();. In our example, that means before we callbar,foocleans itself up and then, rather than callingbaras a subroutine, we do a low-levelgotooperation to the start ofbar.Foo's already cleaned itself out of the stack, so whenbarstarts it looks like whoever calledfoohas really calledbar, and whenbarreturns its value, it returns it directly to whoever calledfoo, rather than returning it tofoowhich would then return it to its caller.
And on tail recursion:
Tail recursion happens if a function, as its last operation, returns the result of calling itself. Tail recursion is easier to deal with because rather than having to jump to the beginning of some random function somewhere, you just do a goto back to the beginning of yourself, which is a darned simple thing to do.
So that this:
sub foo (int a, int b) { if (b == 1) { return a; } else { return foo(a*a + a, b - 1); }
gets quietly turned into:
sub foo (int a, int b) { label: if (b == 1) { return a; } else { a = a*a + a; b = b - 1; goto label; }
What I like about this description is how succinct and easy it is to grasp for those coming from an imperative language background (C, C++, Java)