That’s not TCO that Elm does, it’s self-call tail recursive optimization, it only can happen in fully known contexts and is not general enough to be full TCO. Full Tail Call Optimization is where a call is in the tail-most position of a function, that means you can then compile essentially a goto
to it (or in the Rust proposal a become
for example), this means the call can be dynamically made, can be any amount deep through any amount of function stacks, etc… etc… I really don’t like how the Elm community keeps trying to misrepresent things about the Elm language, it’s an annoying recurring pattern…
In fact, let’s try it, I go to: Try Elm!
And I try running:
import Html exposing (text)
entry f i acc = if i <= 0 then acc else f (i - 1) (acc + i)
dispatch1 i acc = entry dispatch2 i acc
dispatch2 i acc = entry dispatch1 i acc
main =
let i = dispatch1 10000 0 in
text (String.fromInt i)
And the result is:
Initialization Error
InternalError: too much recursion
Well, let’s try this in Elixir, a language that DOES support TCO, so the same code ported running through the repl:
❯ iex
Erlang/OTP 24 [RELEASE CANDIDATE 3] [erts-12.0] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit]
Interactive Elixir (1.12.0-rc.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> defmodule TestingTCO do
...(1)> def entry(f, i, acc), do: if(i <= 0, do: acc, else: f.(i-1, acc+i))
...(1)>
...(1)> def dispatch1(i, acc), do: entry(&dispatch2/2, i, acc)
...(1)>
...(1)> def dispatch2(i, acc), do: entry(&dispatch1/2, i, acc)
...(1)> end
{:module, TestingTCO,
<<70, 79, 82, 49, 0, 0, 7, 176, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 202,
0, 0, 0, 20, 17, 69, 108, 105, 120, 105, 114, 46, 84, 101, 115, 116, 105,
110, 103, 84, 67, 79, 8, 95, 95, 105, 110, ...>>, {:dispatch2, 2}}
iex(2)> TestingTCO.dispatch1(10000, 0)
50005000
And since Elixir really does implement TCO and not just a simple recursive loop optimization unlike elm’s communities repeating lies then we can go way way higher!
iex(3)> TestingTCO.dispatch1(1000000, 0)
500000500000
Elm has a lot of issues both as a language and as a community, and passing off a very very common optimization pass performed in almost every language as TCO is just the tip of the iceberg…