F3.05 · part 3 of 3
Matching on a struct's type
Because a struct carries its module in the __struct__ key, a pattern can
match on the type itself. %User{} = value succeeds only when the value is a
User, and a function can have one clause per struct — the runtime picks the clause
whose tag fits.
The portal passes many shapes around: a %User{}, a
%Session{}, sometimes a plain map from outside. A single
describe/1 dispatches on which one arrives. Send a value through and watch the clause
light up.
Dispatch by the tag
Three clauses, in order: one for %User{}, one for %Session{},
and a final one for any plain map. Choose an incoming value and see which clause matches and why.
The incoming value · select one
The tag turns a value's type into something a pattern can read. One function dispatches across shapes with no conditionals — the clause whose struct matches is the one that runs.
Clause order and the guard
Order matters because a struct is a map: the %{} clause would match a
%User{} too. Putting the struct clauses first, and guarding the map clause with
not is_struct(m), keeps each value with the clause meant for it.
def describe(%User{email: e}), do: "user #{e}" def describe(%Session{id: id}), do: "session #{id}" def describe(%{} = m) when not is_struct(m), do: "plain map of #{map_size(m)} keys" # is_struct/2 asks the tag directly is_struct(user) # => true is_struct(user, User) # => true is_struct(%{a: 1}) # => false
The idea
Choose the right behaviour by looking at a value's type — dispatch by what the thing is.
In Elixir
%Struct{} patterns and is_struct/2 dispatch on the tag — and that tag is what protocols use for polymorphism.
That is the whole of structs: a named, checked shape over a map, with a tag you can match on. Next module: F3.06 — Protocols & behaviours, where that tag drives polymorphism across types.
References
Primary sources for this lesson, and where it connects in the course.
Sources
- Structs — Elixir documentation — named, typed maps and the
__struct__tag. - Keywords and maps — Elixir documentation — choosing a data shape.
Map— Elixir documentation — the map module a struct is built on.