Tail calls, tailrec and trampolines (2009)
blog.richdougherty.com
blog.richdougherty.com
Clojure has also had "trampoline" in core since 1.0, which was released in the same year this article was written: https://clojuredocs.org/clojure.core/trampoline. I have no idea how well it performs though.
If your language has "goto", it is very easy to manually optimize mutually recursive functions. One of the few valid use cases of "goto" today. (As someone who writes a lot of Go, I have always suspected this use case is why Go still has "goto".)
Manually rewriting recursive algorithms is one of the least valid use case of GOTO. You need GOTO for low-level concurrency, IO multiplexing, and transpiling:
https://github.com/vsedach/Eager-Future2/blob/master/future....
https://github.com/vsedach/Vacietis/blob/master/compiler/imp...
https://kangax.github.io/compat-table/es6/#test-proper_tail_...
Discussion on this (apparently controversial!) feature:
People say it blows up the stack traces, so it should be opt-in.
But it seems that Node.js and Safari have it, and as far as I know Safari uses JavaScript Core, which is also used for React-Native.
With time travelling debuggers it might be possible to look at those, but that's a whole new topic.
Sure. But a recursive function can have errors happen in one call that are only detected a few levels down. Given a full call stack, you have a trace of the execution thus far that gives you information about where, exactly, things went wrong. With TCO, you're just left with the original call at the top, and the failed state at the bottom, and no snapshot of what happened in the meanwhile.
Of course this leads to its own problem if your now unoptimised recursive blows the stack...
Kotlin performs tailrec optimisation and is compiled to jvm.
This wouldn't be actual TCO in that case.