This may be somewhat off-topic, but I think the point of "you lose debug stack traces!" is that with tail call elimination, you have more possibility for confusion from people who inadvertently write a tail call, or who write something tail-recursive without caring about the stack growth (e.g. if it only recurses a few times in their use cases). That's where the increased difficulty comes from; of course loops/state machines/tail-recursive functions are hard to debug either way. I guess basically the problem is that with loops you know what you're in for with regards to debugging, whereas tail-recursion is kind of implicit---you have to learn how to recognize a tail call, which is non-trivial, or at least non-trivial compared to distinguishing a loop from a function call.