F3.05 · part 2 of 3
Enforcing keys & defaults
A bare defstruct makes every field optional and nil by default. Two
additions tighten that: @enforce_keys marks fields that must be given, raising at
build time when one is missing, and a keyword form of defstruct sets default values
for the rest.
A portal learner has no meaning without an email, so :email is enforced.
A new learner is a :student and active until told otherwise,
so those carry defaults. Choose what the caller supplies and watch the struct build — or refuse to.
Building with what is given
The struct enforces :email and defaults role: :student and
active: true. Each field below is coloured by where its value comes from —
supplied by the caller, filled from a default, or missing.
What the caller supplies · select one
Defaults remove boilerplate for the common case; @enforce_keys turns a
missing essential field into an error at the moment of construction, not a nil discovered later.
Declaring required keys and defaults
@enforce_keys is a module attribute listing the required fields; the keyword form of
defstruct pairs the rest with defaults. A field can be enforced or defaulted, not
both — a default already guarantees a value.
defmodule Portal.Accounts.User do @enforce_keys [:email] defstruct [:email, role: :student, active: true] end %User{email: "ada@portal.dev"} # => %User{email: "ada@portal.dev", role: :student, active: true} %User{role: :admin} # ** (ArgumentError) the following keys must also be given # when building struct Portal.Accounts.User: [:email]
The idea
Some fields are essential and some have a sensible starting value — the contract of a record.
In Elixir
@enforce_keys raises when an essential field is absent; defstruct defaults fill the rest.
Next: matching on a struct's type
— using the __struct__ tag to dispatch by shape.
References
Primary sources for this lesson, and where it connects in the course.
Sources
- Structs — Elixir documentation — named, typed maps,
@enforce_keys, and defaults. - Keywords and maps — Elixir documentation — choosing a data shape.
Map— Elixir documentation — the map module a struct rests on.