100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Comprehensions in Elixir

Learn Elixir's for special form — a concise syntax for looping over enumerables and generating new collections with filters, multiple generators, and pattern matching.

Data & CollectionsIntermediate9 min readJul 10, 2026
Analogies

Comprehensions in Elixir

A comprehension is Elixir's for special form, which combines one or more generators (x <- enumerable), optional filters, and a result expression into a single concise expression, e.g. for x <- [1, 2, 3], do: x * x produces [1, 4, 9]. Under the hood a comprehension is syntactic sugar over Enum/Stream operations, but it reads more like a mathematical set-builder notation, which makes nested loops, filtered transformations, and cross-products of multiple collections far more readable than the equivalent chain of Enum.map/Enum.filter/Enum.flat_map calls, especially once more than one generator is involved.

🏏

Cricket analogy: for x <- deliveries, x.runs >= 4, do: x mirrors a scorer filtering a full ball-by-ball log down to just the boundaries in one readable pass, instead of chaining multiple manual filters.

Generators, Filters, and Multiple Sources

A comprehension can have more than one generator, and every combination of their values is produced as a cross-product, so for x <- [1, 2], y <- [:a, :b], do: {x, y} yields [{1, :a}, {1, :b}, {2, :a}, {2, :b}] — invaluable for building a grid, a deck of cards, or every pairing between two lists. Filters are plain boolean expressions placed after the generators and separated by commas; every filter must evaluate truthy for a given combination to reach the do: block, and a generator's left-hand side can itself be a pattern that silently skips any element that fails to match, which combines filtering and destructuring in one step.

🏏

Cricket analogy: for team1 <- group_a, team2 <- group_b, do: {team1, team2} mirrors generating every possible group-stage fixture in a World Cup by pairing each Group A team against each Group B team.

The into: Option and Other Collectables

By default a comprehension collects its results into a list, but the into: option redirects the output into any structure that implements the Collectable protocol — into: %{} builds a map, into: "" concatenates strings (handy for building a string character by character), and into: MapSet.new() builds a set, all without an intermediate list allocation. Combined with the uniq: true option, which drops duplicate results, and the reduce: option for accumulating a single value across iterations instead of collecting a list, comprehensions cover a surprising range of use cases well beyond simple mapping.

🏏

Cricket analogy: for p <- players, into: %{}, do: {p.name, p.average} mirrors building a lookup map of batting averages keyed by player name directly from a squad list, instead of a list of pairs.

elixir
# Basic comprehension: list in, transformed list out
squares = for n <- 1..5, do: n * n
# [1, 4, 9, 16, 25]

# Filter: only even numbers, squared
for n <- 1..10, rem(n, 2) == 0, do: n * n
# [4, 16, 36, 64, 100]

# Multiple generators: cross-product
for suit <- [:hearts, :spades], rank <- [:ace, :king, :queen], do: {rank, suit}

# Pattern match in the generator filters out non-matching elements
results = [{:ok, 1}, {:error, :bad}, {:ok, 2}]
for {:ok, value} <- results, do: value
# [1, 2] - the {:error, :bad} tuple simply doesn't match, and is skipped

# into: builds a map instead of a list
for {k, v} <- [a: 1, b: 2], into: %{}, do: {k, v * 10}
# %{a: 10, b: 20}

When a generator's pattern doesn't match an element — like {:ok, value} <- results skipping any {:error, _} tuples — Elixir does not raise a MatchError. Non-matching elements are silently excluded from the comprehension, which is a clean way to combine filtering and destructuring in a single generator clause.

Comprehensions with multiple generators produce a full cross-product, so nesting several large enumerables (for x <- big_list_1, y <- big_list_2, do: ...) can blow up combinatorially — a 10,000-element list crossed with another 10,000-element list produces 100 million results. Add filters early or restructure the logic before reaching for a comprehension at that scale.

  • The for special form combines generators, filters, and a result expression into one readable construct.
  • Multiple generators (x <- a, y <- b) produce every combination as a cross-product.
  • Filters are boolean expressions after the generators; all must be truthy for a combination to be kept.
  • A generator's pattern can itself filter: non-matching elements are silently skipped, no MatchError.
  • into: redirects the result into any Collectable (map, string, MapSet) instead of a list.
  • uniq: true removes duplicates; reduce: accumulates a single value instead of collecting results.
  • Comprehensions with multiple large generators can produce a combinatorial explosion of results.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#ElixirStudyNotes#ComprehensionsInElixir#Comprehensions#Elixir#Generators#Filters#StudyNotes#SkillVeris#ExamPrep