ELIXIR / CHAPTER 06

Structs and explicit domain shape

Intermediate

Use a named data shape without mistaking it for runtime validation.

By the end of this chapter

  • Define a struct with known fields
  • Distinguish construction requirements from value validation
  • Update a struct while preserving its type

The idea

A struct is a map with a named type and a defined set of fields. It documents a domain shape and supports pattern matching on that type. Default values make construction convenient, while @enforce_keys requires selected keys at supported construction points. Requiring a key does not prove that its value has the correct type, range, or meaning.

Keep validation in a constructor function when callers need a trustworthy record. A struct update can require known fields, but generic map operations may produce values that no longer obey the intended struct interface. Prefer operations that retain the struct’s known shape and use pattern matching to distinguish it from an arbitrary map. Immutable updates create new values without modifying existing references.

Elixir example
defmodule TicketRecord do
  @enforce_keys [:id]
  defstruct [:id, priority: 0]
  def demo do
    original = %__MODULE__{id: "t1", priority: 2}
    updated = %{original | priority: 5}
    {original.priority, updated.priority}
  end
end
IO.inspect(TicketRecord.demo())
Result
{2, 5}

The updated struct is a new value. The original retains priority two, and the known field is changed explicitly.

Try it yourself

Write a constructor returning {:ok, struct} only for a nonempty id and nonnegative priority.

Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.

CHECK YOUR UNDERSTANDING

Chapter checkpoint

What does @enforce_keys primarily establish during normal struct construction?