CommunityNews

CommunityNews

Tail-call optimization in Elm

What is TCO?

Tail-call optimization (TCO) is a very neat trick that the Elm compiler does to make recursive functions a lot more performant and stackoverflow-proof.

Evan Czaplicki describes it very well in this article and I recommend you go read it. He calls it tail-call elimination but it’s a different name for the same thing.

To summarize Evan’s article, a “tail-call optimized” function is a recursive function that gets compiled to using a loop instead of function calls to itself. Let’s take the following code as an example…

Read in full here:

This thread was posted by one of our members via one of our news source trackers.

Most Liked

OvermindDL1

OvermindDL1

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…

AstonJ

AstonJ

Even if it’s not true TCO, performance enhancements are always welcome when it comes to JS land :nerd_face:

rustkas

rustkas

I have already read a lot about the disadvantages of Elm. In your opinion, what is currently better than Elm (in terms of the quality of code generation, what to choose for creating a new application) for the front end part?

Where Next?

Popular Frontend topics Top

New
AstonJ
By @kobaltz Here’s a related thread about StimulusReflex - an exciting new way to build modern, reactive, real-time apps with Rails.
New
First poster: bot
Why I Love Tailwind. Why Tailwind is blowing up, why I (the creator of styled-components) love it and how I avoid the downsides of atomi...
New
First poster: bot
How I built a telnet chat server in 2021 with WebAssembly. I love the aesthetics of terminals and I’m not the only one, there is a whole...
New
First poster: bot
clickbait isn’t it? But this was Brock’s immediate reaction when we saw (and I recommend you read this first): Full Third-Party Cookie ...
New
First poster: bot
Hey! We’re getting really close to releasing React + Vue support for Tailwind UI, so I thought it would be interesting to share some of t...
New
First poster: bot
This is a guide for starting a TypeScript project in 2021 with modern tooling. TypeScript 4 Optionally esbuild to bundle for browsers (...
New
First poster: bot
VanillaJS v. jQuery v. hyperscript Below are comparisons of how to implement various common UI patterns in vanilla javascript, jQuery an...
New
First poster: bot
CSS Fingerprinting is a technique of tracking and gathering information on site visitors. This method exploits the nature of CSS to track...
New
brainlid
You are storing some Phoenix LiveView state in the browser. You want to retrieve that saved state as early as possible to improve the use...
New

Other popular topics Top

PragmaticBookshelf
Andy and Dave wrote this influential, classic book to help their clients create better software and rediscover the joy of coding. Almost ...
New
AstonJ
Or looking forward to? :nerd_face:
503 14512 277
New
Exadra37
Please tell us what is your preferred monitor setup for programming(not gaming) and why you have chosen it. Does your monitor have eye p...
New
PragmaticBookshelf
Rust is an exciting new programming language combining the power of C with memory safety, fearless concurrency, and productivity boosters...
New
dimitarvp
Small essay with thoughts on macOS vs. Linux: I know @Exadra37 is just waiting around the corner to scream at me “I TOLD YOU SO!!!” but I...
New
AstonJ
In case anyone else is wondering why Ruby 3 doesn’t show when you do asdf list-all ruby :man_facepalming: do this first: asdf plugin-upd...
New
Exadra37
Oh just spent so much time on this to discover now that RancherOS is in end of life but Rancher is refusing to mark the Github repo as su...
New
PragmaticBookshelf
Build efficient applications that exploit the unique benefits of a pure functional language, learning from an engineer who uses Haskell t...
New
New
New