F3.05 · part 1 of 3
Defining a struct
A struct is declared inside a module with defstruct, which lists the
fields the struct may hold. The module's name becomes the struct's name, so
Portal.Accounts.User defines the %User{} shape. At runtime a
struct is an ordinary map carrying one extra key, __struct__, set to the module.
The portal needs a learner with a guaranteed shape: an id, an email, and a role. One
defstruct line gives every %User{} exactly those fields and
nothing else.
A struct is a tagged map
The %User{} literal is sugar over a map. It shows the fields you set, but the same
value also carries a hidden __struct__ key naming its module. Switch between the
views to see the one value three ways.
One value, three views · select one
The literal and the map are the same value. The __struct__ key is the only
thing that separates a struct from a plain map — and it is what lets a later clause match on the type.
Declaring the fields
The declaration is one line. defstruct takes a list of field names; building a value
with an unknown key is a compile error, which is the guarantee a plain map cannot give.
defmodule Portal.Accounts.User do defstruct [:id, :email, :role] end # build one — and look underneath user = %Portal.Accounts.User{id: "USR0NbAb1xcFCy", email: "ada@portal.dev", role: :student} user.__struct__ # => Portal.Accounts.User Map.keys(user) # => [:__struct__, :email, :id, :role] is_map(user) # => true
F2.07 · product types
A product type bundles a fixed set of fields into one value — all present together.
F3 · defstruct
The same product, named by its module and backed by a map — the fields are fixed, the shape is checked.
Next: enforcing keys and defaults — making some fields required and giving others a starting value.
References
Primary sources for this lesson, and where it connects in the course.
Sources
- Keywords and maps — Elixir documentation — choosing a data shape.
- Structs — Elixir documentation — named, typed maps.
Map— Elixir documentation — the map module.