Elixir Data Types
A tour of Elixir's core built-in types -- atoms, tuples, lists, maps, and more -- and when to reach for each one.
3 min read
Elixir has a compact set of built-in data types, and understanding what each one is for makes the rest of the language click much faster.
Numbers
integer = 42
float = 3.14
big = 1_000_000 # underscores for readability
hex = 0xFFIntegers in Elixir have arbitrary precision — they don't overflow like fixed-width integers in some languages. Division with / always returns a float; use div/2 and rem/2 for integer division and remainder.
Atoms
An atom is a constant whose name is its own value — think of it like an enum member with no extra ceremony:
status = :ok
color = :redAtoms are everywhere in idiomatic Elixir, especially as tags in tuples like {:ok, result} or {:error, reason}, which you'll see constantly once functions and pattern matching are introduced. true, false, and nil are actually atoms (:true, :false, :nil) under the hood.
Strings and binaries
greeting = "Hello, world!"Elixir strings are UTF-8 encoded binaries, wrapped in double quotes. Single quotes create a charlist instead ('hello'), an older representation mostly kept for Erlang interop — stick to double-quoted strings for normal code.
Tuples
A tuple is a fixed-size, ordered collection, best used for a small, known number of related values:
point = {3, 4}
result = {:ok, "user created"}Tuples are commonly used as return values that pair a status atom with a payload — {:ok, value} or {:error, reason} is a pattern you'll see in nearly every Elixir library.
Lists
A list is a variable-length, linked collection:
numbers = [1, 2, 3, 4]
mixed = [1, "two", :three, 4.0]Lists can hold mixed types and grow or shrink, but because they're implemented as linked lists, accessing an element by index is slow for large lists — prepending to the front ([item | list]) is fast, while appending to the end or indexing into the middle is not.
Maps
A map is a key-value store, Elixir's go-to for structured data:
user = %{name: "Ada", age: 30}
user.name
# => "Ada"
user[:age]
# => 30When keys are atoms, %{name: "Ada"} is shorthand for %{:name => "Ada"}, and dot access (user.name) works. Maps with non-atom keys need the full arrow syntax: %{"name" => "Ada"}, and only bracket access (user["name"]) works for those.
Booleans and nil
is_active = true
result = nilnil represents the absence of a value, similar to null/None elsewhere. Elixir treats nil and false as the only "falsy" values — everything else, including 0 and "", is truthy.
Choosing the right type
A rough rule of thumb: use a tuple for a small fixed group of values (especially {:ok, _}/{:error, _} returns), a list for an ordered, arbitrary-length sequence, and a map for anything you'd reach for a dictionary or object for in another language. The next lesson, on pattern matching, shows why this distinction between fixed-shape (tuples) and variable-shape (lists) data matters even more than it might seem right now.
Test what you just learned
4 quick questions. Get all of them right to unlock the next lesson.
You can take the quiz without an account — logging in just lets your result count toward your progress.