Pattern matching changed how I write code
The feature I miss most when I leave Elixir isn’t the concurrency model or the pipe operator — it’s pattern matching. Once it clicks, branching code starts to feel clumsy by comparison.
Destructure at the door
Instead of pulling values out inside a function, you match them in the signature:
def greet(%{name: name, role: "admin"}), do: "Welcome back, #{name}"
def greet(%{name: name}), do: "Hi, #{name}"
The shape of the data is the control flow. There’s no if user.role == ...
buried three lines down — the dispatch happens before the body even runs.
Let it crash
Matching also doubles as an assertion:
{:ok, result} = do_work()
If do_work/0 returns an error tuple, this line fails loudly and immediately,
right where the wrong assumption lives — not five functions later with a nil
that’s hard to trace. Combined with supervisors, “let it crash” stops being
reckless and starts being a design.
The takeaway
Pattern matching pushed me to model data more deliberately in every language — to make the shape of a value carry meaning, and to fail close to the mistake. That habit travels, even when the syntax doesn’t.