Appearance
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__/1A struct is named after the module that defines it. Only the fields listed in defstruct may exist.
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.
elixir
is_map(john) #=> true
john.__struct__ #=> UserBut 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.