Let's say I have a simple function like this:
int all_true(int* bools, int len) {
if (len < 1) return TRUE;
return *bools && all_true(bools+1, len-1);
}
This function can be rewritten in a more obviously tail-recursive style as follows:
int all_true(int* bools, int len) {
if (len < 1) return TRUE;
if (!*bools) return FALSE;
return all_true(bools+1, len-1);
}
Logically, there is zero difference between the two; assuming bools
contains only TRUE
or FALSE
(sensibly defined), they do exactly the same thing.
My question is: if a compiler is smart enough to optimize the second as a tail-recursive call, is it reasonable to expect it to optimize the first in the same way, given that "&&" short-circuits? Obviously, if a non-short-circuiting operator were used, this would not be tail-recursive because both expressions would be evaluated before the operator is even applied, but I'm curious about the short-circuited case.
(Before I get a flood of comments telling me that C compilers don't usually optimize tail-recursive calls: consider this to be a general question about optimizing tail-recursive calls with short-circuit operators, independent of language. I'll be happy to rewrite this in Scheme, Haskell, OCaml, F#, Python, or what the heck ever else for you if you don't understand C.)