Elixir Data Types
Elixir is dynamically typed: a variable's type is determined at runtime by whatever value is currently bound to it, and the compiler does not require type annotations. Every value in Elixir is immutable, so 'modifying' a list or map does not change it in place, it produces a brand new value while the original remains untouched in memory until garbage collected. Understanding the handful of built-in data types, numbers, atoms, booleans, strings, lists, tuples, and maps, is the foundation for everything else in the language, including pattern matching and the standard library's Enum and Map modules.
Cricket analogy: Elixir's dynamic typing is like a franchise selector who judges a net bowler by the ball just delivered rather than a fixed designation on paper, an all-rounder like Ravindra Jadeja can bowl one over and bat the next without needing separate certification for each role.
Numbers, Atoms, and Booleans
Elixir integers have arbitrary precision, so they grow automatically to hold arbitrarily large values without ever overflowing, unlike the fixed-width integers in languages such as Java or C. Floats are 64-bit IEEE 754 doubles, and Elixir will not silently coerce an integer to a float or vice versa in comparisons using ===, though == does allow numeric comparison across the two. Atoms, written with a leading colon such as :ok, :error, or :my_atom, are constants whose name is their own value; true, false, and nil are simply atoms in disguise, which is why they can be pattern matched exactly like any other atom.
Cricket analogy: Atoms like :ok and :error are like standardized umpire signals on a cricket field, a raised finger always means out and a horizontal arm wave always means wide, fixed named symbols the entire ground understands instantly without further explanation.
Strings and Binaries
Double-quoted text such as "hello" is a UTF-8 encoded binary in Elixir, and supports interpolation with the #{} syntax to embed the result of any expression directly inside the string. Single-quoted text such as 'hello', by contrast, is a charlist, a list of integer Unicode codepoints, and is not the same data type as a binary string even though the two often print similarly in iex. This distinction matters because most of the String module's functions, like String.upcase/1 or String.split/2, operate on binaries, not charlists, and passing the wrong type produces confusing FunctionClauseError messages for beginners.
Cricket analogy: Mixing up strings and charlists is like confusing a Test match scorecard with a quick SMS score update reading India 250/4, both carry similar information but are structured completely differently underneath.
iex> "hello" <> " " <> "world"
"hello world"
iex> name = "Ada"
iex> "Hello, #{name}! You have #{2 + 3} new messages."
"Hello, Ada! You have 5 new messages."
iex> is_binary("hello")
true
iex> is_list('hello')
trueSingle-quoted strings like 'hello' are charlists, lists of integer codepoints, NOT the same as double-quoted binary strings "hello". They can look identical in casual code but behave completely differently: String.upcase('hello') raises a FunctionClauseError because String functions expect binaries. When in doubt, use double quotes for text in modern Elixir code.
Collections: Lists, Tuples, and Maps
Lists, written [1, 2, 3], are singly-linked lists internally, which makes prepending an element with [0 | list] a cheap constant-time operation, but accessing an arbitrary index is O(n) because Elixir must walk the list node by node from the head. Tuples, written {:ok, 42}, are fixed-size and stored contiguously in memory, giving O(1) indexed access via elem/2, which is why Elixir idiomatically uses small tuples like {:ok, result} or {:error, reason} to tag the outcome of an operation. Maps, written %{name: "Ada", age: 36}, are Elixir's general-purpose key-value structure, supporting any term as a key and efficient lookup, while keyword lists, written [timeout: 5000, retries: 3], are ordered lists of two-element tuples with atom keys and are conventionally used for optional function arguments.
Cricket analogy: A tuple like {:ok, 254} for a completed run-chase is like a fixed two-slot scoreboard entry, status then value, instantly pattern matched to check the outcome before touching the number, whereas a list of every ball bowled in the innings must be walked delivery by delivery to find the twentieth over.
iex> [head | tail] = [10, 20, 30]
[10, 20, 30]
iex> head
10
iex> tail
[20, 30]
iex> point = {:ok, 42}
iex> elem(point, 1)
42
iex> user = %{name: "Ada", age: 36}
iex> user.name
"Ada"
iex> %{user | age: 37}
%{age: 37, name: "Ada"}
iex> opts = [timeout: 5000, retries: 3]
iex> Keyword.get(opts, :timeout)
5000%{user | age: 37} is Elixir's update syntax for maps: it produces a new map with age replaced, leaving user untouched, and it is more efficient than Map.put/3 because it requires the key to already exist, letting the runtime skip a full key-existence check.
- Elixir is dynamically typed; a value's type is checked at runtime, not compile time.
- Integers have arbitrary precision; floats are 64-bit IEEE 754 doubles.
- Atoms are named constants whose value is their own name; true, false, and nil are atoms.
- Double-quoted strings are UTF-8 binaries; single-quoted strings are charlists, and the two are not interchangeable.
- Lists are linked lists: cheap to prepend, O(n) to access by index.
- Tuples are fixed-size and contiguous, giving O(1) access, ideal for tagged results like {:ok, value}.
- Maps provide general key-value storage; keyword lists are ordered and allow duplicate atom keys, often used for options.
Practice what you learned
1. Which of these is a charlist rather than a binary string in Elixir?
2. What is the time complexity of accessing an element by index in an Elixir list?
3. Which data type is most idiomatically used for tagged results like {:ok, value} or {:error, reason}?
4. What are true and false actually implemented as in Elixir?
5. Which syntax defines a map with an atom key name in Elixir?
Was this page helpful?
You May Also Like
What Is Elixir?
An introduction to Elixir, a functional, concurrent programming language built on the Erlang VM for building scalable and fault-tolerant applications.
Pattern Matching in Elixir
How Elixir's = operator performs structural pattern matching rather than simple assignment, and how that idea powers destructuring, function clauses, and control flow.
Your First Elixir Program
Write, run, and understand your first Elixir program, from a standalone script to a proper Mix module with functions and a test.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics