Reading Elixir as a JS developer

LLM-authored, human-reviewed

Foundations

By the time you write your first Elixir at Algebraic Laws, the functional thinking is already in place. Map that thinking onto new syntax. This cheat sheet makes that mapping concrete; it is not a full language tutorial. For that, use the outbound links at the bottom.

The core mapping

JavaScript Elixir Notes
const x = 5; x = 5 Elixir has no let/var distinction - but see “rebinding,” below.
arr.map(fn) Enum.map(arr, fn) Same idea, subject and verb swapped.
arr.filter(fn) Enum.filter(arr, fn) Same swap.
arr.reduce(fn, init) Enum.reduce(arr, init, fn) Note the argument order changes.
a.b.c(x) x |> a.b.c() The pipe operator: “take this value, feed it into the next call.”
function f(x) { ... } def f(x) do ... end Elixir functions live inside a defmodule, always.
if (x) { a } else { b } if x, do: a, else: b Elixir’s if is an expression - it returns a value.
switch / pattern-ish if chains case x do ... end Elixir’s pattern matching is far more capable than switch.
{ name: "x", age: 1 } %{name: "x", age: 1} Maps look almost identical to object literals.
JSON.stringify mental model Elixir has no implicit toString Explicit conversion (to_string/1, inspect/1) is the norm.

The one habit that will actually trip you up: rebinding

The mapping that matters most is rebinding. It gets its own section.

let total = 0;
for (const x of items) {
  total = total + x;   // mutate the same variable
}
total =
  Enum.reduce(items, 0, fn x, acc ->
    acc + x   # acc is a NEW binding each call, not a mutation
  end)

total = total + x mutates a variable in place. Elixir does not do that. In Elixir, x = x + 1 creates a new binding named x that shadows the old one; it never mutates anything in memory. That is what Substitutions and Functions drilled: an expression reduces to a value by replacing, never by changing in place. If you did those steps, the idea is not new. This is the first time you are seeing it with Elixir’s = instead of substitution arrows.

Batteries included: the utilities your language already ships

The table handles syntax. The bigger difference is the standard library’s shape: JavaScript gives you a few primitives and leaves the loops to you; Elixir’s Enum module ships the loop itself. The same five jobs - make a range, split a list into chunks, pair two lists positionally, number the elements, take the first terms of an infinite sequence - take one Enum call in Elixir and a hand-written loop (or a for) in TypeScript.

These exercises pose the same problem in both languages. Solve them and compare where the work happens:

  • Range - Enum.to_list(Range.new(1, 5, 1)) vs. a loop that pushes start + i * step.
  • Chunk - Enum.chunk_every/2 vs. slice in a loop.
  • Zip - Enum.zip/2 vs. a loop over Math.min of the two lengths.
  • Enumerate - Enum.with_index/2 vs. map with the index argument.
  • Sequence Take - Stream.iterate/2 + Enum.take/2 vs. a bounded loop. The Elixir version never materialises the infinite sequence - the lazy stream is the point.

Solve each in Elixir first, then in TypeScript. The lesson is not that one language is better. It is where the loop lives. Reaching for the builtin is a skill, not a shortcut.

Where the syntax table stops being enough

A cheat sheet gets you reading Elixir. It will not teach you Enum vs. Stream, OTP, pattern matching in function heads, or the pipe operator’s real power. Use these resources next:

Take what you learn there back to Algorithms and practice it here. This site does not replace those resources; it is where you drill what they teach.

Related exercises

  • problem Two Sum
← Back to articles