Gleam Lists
A list holds an ordered sequence of values, all of the same type. Lists in Gleam are immutable singly-linked lists — the same structure used in functional languages like Haskell and Erlang. They excel at sequential processing and pattern matching.
Creating Lists
let fruits = ["apple", "banana", "cherry"]
let primes = [2, 3, 5, 7, 11]
let empty = []
let single = ["only one"]All elements must share the same type. A list of String cannot contain an Int.
How Lists Work Internally
Singly-Linked List Diagram
──────────────────────────────────────────────────
[1, 2, 3, 4]
┌───┬──┐ ┌───┬──┐ ┌───┬──┐ ┌───┬────┐
│ 1 │ ─┼──▶│ 2 │ ─┼──▶│ 3 │ ─┼──▶│ 4 │ [] │
└───┴──┘ └───┴──┘ └───┴──┘ └───┴────┘
head tail = []
Each element holds a value and a pointer to the next element. The last element points to an empty list []. This structure makes adding to the front fast — and everything else slower, which shapes how you write list algorithms.
Prepending to a List
Adding to the front of a list is instant — it creates a new head that points to the existing list:
let tail = [2, 3, 4]
let full = [1, ..tail]
// [1, 2, 3, 4]
Prepend Diagram
──────────────────────────────────────────────────
tail = [2, 3, 4]
After [1, ..tail]:
┌───┬──┐
│ 1 │ ─┼──▶ [2, 3, 4] (original, unchanged)
└───┴──┘
The ..tail syntax spreads the existing list. The original list stays intact — Gleam creates a new list with 1 at the front.
The gleam/list Module
Frequently Used list Functions
──────────────────────────────────────────────────────────
Function │ Description
──────────────────────────┼───────────────────────────────
list.length(l) │ Count of elements
list.first(l) │ First element → Result
list.last(l) │ Last element → Result
list.append(a, b) │ Join two lists
list.reverse(l) │ Reverse order
list.map(l, f) │ Transform each element
list.filter(l, f) │ Keep matching elements
list.fold(l, init, f) │ Reduce to one value
list.contains(l, v) │ Check if value exists
list.flatten(l) │ Flatten nested lists
list.take(l, n) │ First n elements
list.drop(l, n) │ Drop first n elements
list.sort(l, compare) │ Sort elements
list.zip(a, b) │ Pair elements together
map — Transform Every Element
import gleam/list
let prices = [100, 200, 300]
let discounted = list.map(prices, fn(p) { p - 10 })
// [90, 190, 290]
map Diagram
──────────────────────────────────────────────────
[100, 200, 300]
│ │ │
▼ ▼ ▼
-10 -10 -10
│ │ │
▼ ▼ ▼
[90, 190, 290]
filter — Keep Matching Elements
let scores = [45, 80, 60, 95, 30, 72]
let passing = list.filter(scores, fn(s) { s >= 60 })
// [80, 60, 95, 72]fold — Reduce to One Value
let numbers = [1, 2, 3, 4, 5]
let total = list.fold(numbers, 0, fn(acc, n) { acc + n })
// total = 15
fold Step-by-Step
──────────────────────────────────────────────────
Start: acc = 0
Step 1: acc = 0 + 1 = 1
Step 2: acc = 1 + 2 = 3
Step 3: acc = 3 + 3 = 6
Step 4: acc = 6 + 4 = 10
Step 5: acc = 10 + 5 = 15
Result: 15
Pattern Matching on Lists
The most powerful way to process a list is recursive pattern matching:
pub fn sum(numbers: List(Int)) -> Int {
case numbers {
[] -> 0
[head, ..tail] -> head + sum(tail)
}
}
// sum([1, 2, 3])
// = 1 + sum([2, 3])
// = 1 + 2 + sum([3])
// = 1 + 2 + 3 + sum([])
// = 1 + 2 + 3 + 0
// = 6
Recursive sum([1, 2, 3])
──────────────────────────────────────────────────
sum([1, 2, 3])
head=1, tail=[2,3]
1 + sum([2, 3])
head=2, tail=[3]
2 + sum([3])
head=3, tail=[]
3 + sum([])
→ 0
3 + 0 = 3
2 + 3 = 5
1 + 5 = 6
Checking and Searching
import gleam/list
let fruits = ["apple", "mango", "banana"]
let has_mango = list.contains(fruits, "mango") // True
let count = list.length(fruits) // 3
let first = list.first(fruits) // Ok("apple")
let last = list.last(fruits) // Ok("banana")
let empty_list = []
let nothing = list.first(empty_list) // Error(Nil)
Sorting a List
import gleam/list
import gleam/int
let values = [5, 1, 8, 3, 9, 2]
let sorted = list.sort(values, int.compare)
// [1, 2, 3, 5, 8, 9]
Zipping Two Lists
let names = ["Alice", "Bob", "Carol"]
let scores = [90, 78, 95]
let pairs = list.zip(names, scores)
// [#("Alice", 90), #("Bob", 78), #("Carol", 95)]
Zip Diagram
──────────────────────────────────────────────────
names: ["Alice", "Bob", "Carol"]
scores: [90, 78, 95 ]
│ │ │
▼ ▼ ▼
pairs: [#("Alice",90), #("Bob",78), #("Carol",95)]
Practical Example — Student Report
import gleam/list
import gleam/io
import gleam/int
pub fn class_average(scores: List(Int)) -> Int {
let total = list.fold(scores, 0, fn(acc, s) { acc + s })
let count = list.length(scores)
total / count
}
pub fn top_scorers(scores: List(Int), threshold: Int) -> List(Int) {
list.filter(scores, fn(s) { s >= threshold })
}
pub fn main() {
let scores = [72, 88, 91, 65, 79, 95, 83]
io.debug(class_average(scores)) // 81
io.debug(top_scorers(scores, 85)) // [88, 91, 95]
}Key Points
List Essentials
──────────────────────────────────────────────────
1. All elements must share the same type
2. Immutable — functions return new lists
3. Prepend with [new_item, ..existing_list]
4. Use list.map for transformation
5. Use list.filter for selection
6. Use list.fold for aggregation
7. Pattern match [head, ..tail] for recursion
8. list.first / list.last return Result types
Lists are the backbone of functional programming in Gleam. Mastering map, filter, and fold gives you the tools to process any collection without writing a single loop.
