Gleam Tuples

A tuple groups a fixed number of values of different types into one unit. Tuples are lightweight and need no type declaration — you create them instantly with the #() syntax. They are perfect for returning multiple values from a function or grouping related data without defining a full record type.

Creating Tuples

let point = #(10, 20)
let person = #("Aditya", 28, True)
let rgb = #(255, 128, 0)
let pair = #("key", 42)

Tuple Memory Diagram
──────────────────────────────────────────────────
let person = #("Aditya", 28, True)

┌──────────┬────┬───────┐
│ "Aditya" │ 28 │ True  │
└──────────┴────┴───────┘
  position   0    1    2

Tuple positions start at 0. Each position holds a value of any type. The tuple's type captures the type at each position — #(String, Int, Bool) in the example above.

Accessing Tuple Elements

Use pattern matching to extract elements from a tuple:

let point = #(40, 75)
let #(x, y) = point
// x = 40, y = 75

For two-element tuples, the standard library provides helper functions:

import gleam/pair

let coords = #(40, 75)
let x = pair.first(coords)   // 40
let y = pair.second(coords)  // 75

Tuples in Function Returns

Functions can only return one value. Wrap multiple values in a tuple to return them together:

pub fn min_max(a: Int, b: Int, c: Int) -> #(Int, Int) {
  let minimum = case a < b && a < c { True -> a, False -> case b < c { True -> b, False -> c } }
  let maximum = case a > b && a > c { True -> a, False -> case b > c { True -> b, False -> c } }
  #(minimum, maximum)
}

pub fn main() {
  let #(lo, hi) = min_max(8, 3, 15)
  // lo = 3, hi = 15
}

Return Tuple Flow
──────────────────────────────────────────────────
min_max(8, 3, 15)
        │
        └── computes minimum = 3
        └── computes maximum = 15
        └── returns #(3, 15)

Caller:
let #(lo, hi) = min_max(8, 3, 15)
// lo = 3, hi = 15

Tuple Types

The type of a tuple lists the types at each position:

let a: #(Int, String)       = #(1, "one")
let b: #(Bool, Float, Int)  = #(True, 3.14, 42)
let c: #(String, String)    = #("hello", "world")

Discarding Tuple Elements

Use _ to ignore specific elements you do not need:

let person = #("Priya", 30, "Engineer")

let #(name, _, role) = person
// name = "Priya", role = "Engineer", age ignored

Tuples in Pattern Matching

Tuples work naturally with case expressions for multi-dimensional decisions:

pub fn format_coordinates(point: #(Int, Int)) -> String {
  case point {
    #(0, 0) -> "Origin"
    #(x, 0) -> "On X-axis: " <> int.to_string(x)
    #(0, y) -> "On Y-axis: " <> int.to_string(y)
    #(x, y) -> "(" <> int.to_string(x) <> ", " <> int.to_string(y) <> ")"
  }
}

When to Use Tuples vs Records


Tuples vs Records — Decision Guide
──────────────────────────────────────────────────
Situation                        │ Use
─────────────────────────────────┼──────────────
Temporary, short-lived grouping  │ Tuple
Returning 2–3 values from a fn   │ Tuple
Data with named fields (clarity) │ Record
Data shared across many functions│ Record
More than 3 fields               │ Record

Tuples shine for small, local groupings where defining a full type would be overkill. When data grows or travels across functions, a named record type (covered in the next topic) provides better documentation.

Practical Example — Quotient and Remainder

import gleam/io

pub fn divide_with_remainder(dividend: Int, divisor: Int) -> #(Int, Int) {
  let quotient  = dividend / divisor
  let remainder = dividend % divisor
  #(quotient, remainder)
}

pub fn main() {
  let #(q, r) = divide_with_remainder(17, 5)
  io.debug(q)   // 3
  io.debug(r)   // 2
  // 17 = 5×3 + 2
}

Divide 17 by 5
──────────────────────────────────────────────────
17 ÷ 5

█████ █████ █████ ██  ←  17 items
│     │     │     │
└─────┴─────┘     └── remainder = 2
  3 groups of 5

Result: #(3, 2)  → quotient = 3, remainder = 2

Nested Tuples

let matrix_cell = #(#(2, 3), "value")
let #(#(row, col), data) = matrix_cell
// row = 2, col = 3, data = "value"

Key Points


Tuple Summary
──────────────────────────────────────────────────
1. Created with #(value1, value2, ...)
2. Fixed length — cannot add or remove elements
3. Elements can be different types
4. Access by pattern matching or pair.first/second
5. Type includes the type at each position
6. Use _ to ignore elements you don't need
7. Best for small, local groupings

Tuples are the simplest composite type in Gleam. They hold multiple values together without any overhead — no field names, no declarations, no boilerplate. Reach for them whenever you need a quick way to group two or three related values.

Leave a Comment

Your email address will not be published. Required fields are marked *