>> How do you test for it? Say I have some big program which depends on
>> tail recursion in hundreds of places. What if tail recursion isn't
>> happening in some of them?
> Testing tail calls is pretty easy, since it's a syntactically
> verifiable property. (And in fact there are things that do exactly
> what you want here.)
Having looked at the trace functionality in Racket (do-traced in collects/racket/tracke.rkt), I'm not seeing the simplicity of detecting tail calls. ;)
At least some respectable lispers say to think about tail calls semantically, not syntactically. In their eyes, the tail call isn't an optimization; to create the extra stack frame is a wasteful pessimization.
I somewhat agree with Kaz; IMO the tail position is a subtlety and it does not explicitly show intent. I would like an explicit (tailcall #'f ...) that acts like funcall, but the compiler signals if the function is not in a tail call position. This tailcall form is more to document intent to other humans (and to catch poorly-written macros, like a naive TRACE) than it is to help the compiler. A corresponding notailcall would force the extra stack frame (presumably for debugging).
A different name would help too. Something that better evokes the elision of a stack frame. Declarations might work; but CL does not support them in arbitrary locations...
Maybe I just haven't written enough Scheme code to get a feel for the culture. C++ has its share of gotchas that I've learned to live with.