Skip to content

Structs ​

Source: Elixir guide, Structs.

Structs extend maps with compile-time checks and default values.

Defining and building ​

elixir
defmodule User do
  defstruct name: "John", age: 27
end

%User{}                #=> %User{age: 27, name: "John"}
%User{name: "Jane"}    #=> %User{age: 27, name: "Jane"}
%User{oops: :field}    #=> ** (KeyError) key :oops not found expanding struct: User.__struct__/1

A struct is named after the module that defines it. Only the fields listed in defstruct may exist.

Unknown keys are rejected while compiling, not at runtime.

Access, update, match ​

Access and update work like a map with fixed keys. The update syntax never adds keys, so the underlying maps can share their key structure in memory.

elixir
john = %User{}
john.name                  #=> "John"
jane = %{john | name: "Jane"}
%{jane | oops: :field}     #=> ** (KeyError)

%User{name: name} = john   # name = "John"
%User{} = %{}              #=> ** (MatchError)

%User{} = value checks that the value is a User struct. To update from a keyword list or map with unknown fields, use struct!/2, which raises on invalid fields, instead of Map functions.

Structs are bare maps underneath ​

A struct is a map with one extra key, __struct__, holding the module name.

Same map, plus __struct__.
elixir
is_map(john)       #=> true
john.__struct__    #=> User

But structs don't inherit map features. john[:name] fails (no Access behaviour) and Enum.each(john, …) raises Protocol.UndefinedError. You attach behaviour like this with protocols.

Defaults and required keys ​

Omitted defaults are nil. Fields with implicit nil must come first, then the keyword list:

elixir
defstruct [:email, name: "John", age: 27]

@enforce_keys [:make] makes a key mandatory when building, or ArgumentError at compile time. It isn't checked on updates and it doesn't validate values.

Site code: MIT. Pages and diagrams are derived from the Elixir documentation (Apache-2.0). Not affiliated with the Elixir Team.