Pattern matching is great.

Strictly speaking, I could end this post right here, but occasionally I have an interesting Elixir feature on hand. That is related to pattern matching. That is, I bet, not widely known at all.

One can pattern match on dynamic struct type with pin operator Kernel.SpecialForms.^/1. It’s documentation says:

Accesses an already bound variable in match clauses. Also known as the pin operator.

Not quite expressive, neither informative. But while a documentation walks, the code talks. Check this:

iex|1 ▶ defmodule MyMod, do: defstruct ~w|foo bar|a
iex|2 ▶ mod_ok = MyMod
iex|3 ▶ mod_ko = Integer
iex|4 ▶ %^mod_ok{} = %MyMod{foo: 42, bar: 3.14}
#⇒ %MyMod{bar: 3.14, foo: 42}
iex|5 ▶ %^mod_ko{} = %MyMod{foo: 42, bar: 3.14}
#⇒ ** (MatchError) no match of right hand side value:
#       %MyMod{bar: 3.14, foo: 42}

Wow. We can explicitly pattern match on dynamic struct types! It also works in case clauses:

iex|6 ▶ case %MyMod{foo: 42, bar: 3.14} do
...|6 ▶   %^mod_ok{} = %{foo: _foo} ->
...|6 ▶     IO.inspect(mod_ok, label: "Pinned module")
...|6 ▶ end
#⇒ Pinned module: MyMod

FWIW, the latter might be used without a pin oerator to get the struct type

iex|7 ▶ case %MyMod{foo: 42, bar: 3.14} do
...|7 ▶   %mod{} -> IO.inspect(mod, label: "Matched module")
...|7 ▶ end
#⇒ Matched module: MyMod

This match is the cumbersome spelling of %MyMod{foo: 42, bar: 3.14}.__struct__, though.


Permalink to the Elixir codebase: MapTest.exs.