5 ms·
TCO is available in plenty of other languages as well. Scala, Clojure, Erlang, and Elixir support it out of the box. Ruby has a VM setting for it, and there was
by actsasbuffoon 12y ago
TCO is available in plenty of other languages as well. Scala, Clojure, Erlang, and Elixir support it out of the box. Ruby has a VM setting for it, and there was a proposal to add it to JavaScript. I'm sure there are plenty of others.
- supahfly_remix 12y agoThanks, that's good to know.
- TickleSteve 12y agoJust to be picky.... Clojure doesn't have TCO, it has 'recur' as a substitute instead.
- ch4s3 12y agoTo add a finer point, Clojure doesn't have TCO per se because the JVM doesn't have tco. Recur optimizes the special case of "tail-recursive self-call and not the generalized tail call."[0] That is to say when the tail of A calls A, but not when A calls B which calls A. [0] "The Joy of Clojure," Fogus and Houser
- noblethrasher 12y agoInterestingly, the 64bit CLR JIT does TCO while the 32 bit variety does not.
- kvb 12y agoThat's not accurate. In fact, in the .NET 2.0 timeframe the opposite was the case (the 64-bit JIT would fail to honor the IL tail. prefix in many cases, though it would also make tail calls in other cases even when the prefix wasn't applied)[1]. But as of .NET 4.0, both platforms honor the tail. prefix except in a very limited set of circumstances[2] (e.g. calls from untrusted code to trusted code). As far as I know, F# is the only reasonably popular .NET language to emit the tail. prefix, though[3]. [1] http://blogs.msdn.com/b/davbr/archive/2007/06/20/tail-call-jit-conditions.aspx http://blogs.msdn.com/b/davbr/archive/2007/06/20/tail-call-j... [2] http://blogs.msdn.com/b/clrcodegeneration/archive/2009/05/11/tail-call-improvements-in-net-framework-4.aspx http://blogs.msdn.com/b/clrcodegeneration/archive/2009/05/11... [3] http://blogs.msdn.com/b/fsharpteam/archive/2011/07/08/tail-calls-in-fsharp.aspx http://blogs.msdn.com/b/fsharpteam/archive/2011/07/08/tail-c...
- lostcolony 12y agoPer ch4s3's comment on Clojure, Scala also does not have TCO, at least, last I checked. The JVM doesn't allow it. It has a specialized handling of functions that call themselves, which it can optimize, but A that calls B that calls A that etc is not (nor, in the more general case where any function that ends with a function is removed from the stack).
- pjmlp 12y agoYes it does. That is an implementation detail. It doesn't matter if it is does at compiler or whatever runtime is targeted. This is called lowering in compiler design speak.
- deleted 12y ago[deleted]
- lostcolony 12y agoUmm...yes, it does matter. Closures? Can't be optimized. Polymorphic method? Can't be optimized (even if every implementation is tail recursive). This is more than an implementation detail, it actively influences the way you write your code. And Scala -doesn't- optimize A calls B calls A etc cases. It requires the developer to explicitly make use of scala.util.control.TailCalls. See http://www.scala-lang.org/api/2.11.2/index.html#scala.util.control.TailCalls$ http://www.scala-lang.org/api/2.11.2/index.html#scala.util.c... and associated white paper. What Scala gives you is that if A calls A (calls A calls A), and is tail recursive, and A can not be overridden, it will optimize it.