Tuples

Reviewed & published by Brayan K

Tuples bundle a handful of values into one. By the end of this lesson you'll group values, name and decompose their elements, and return multiple values from a function — Swift's lightweight alternative to a one-off struct.

Part of the free Swift course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ Grouping Values

A tuple combines several values — possibly of different types — into one. Access elements by position with .0, .1, and so on (zero-based).

// A TUPLE groups several values into one compound value.
// The values can be different types.
let person = ("Ada", 36)            // (String, Int)

// Access by POSITION with .0, .1, ... (zero-based).
print(person.0)                     // Ada
print(person.1)                     // 36

// You can annotate the type explicitly:
let coord: (Double, Double) = (1.5, 2.0)
print(coord.0, coord.1)             // 1.5 2.0

2️⃣ Named Elements

Give elements names for readability — (x: 3, y: 5) — then read them by label like point.x. Positional access still works too.

// NAME the elements for readability — then access them by label.
let point = (x: 3, y: 5)
print(point.x)                      // 3
print(point.y)                      // 5

// Named tuples still support positional access too.
print(point.0)                      // 3

// Mixed types are fine and common:
let httpStatus = (code: 404, message: "Not Found")
print("\(httpStatus.code): \(httpStatus.message)")   // 404: Not Found

3️⃣ Decomposition

Unpack a tuple's elements into separate constants in one statement. Use _ to skip parts you don't need. This pattern is everywhere in Swift loops over pairs.

// DECOMPOSE a tuple into separate constants in one line.
let http = (200, "OK")
let (code, message) = http
print("Code \(code), message \(message)")     // Code 200, message OK

// Use _ to ignore parts you don't need.
let point = (x: 10, y: 20)
let (justX, _) = point
print("x is \(justX)")                          // x is 10

// Decomposition shines in loops over (key, value) pairs:
for (name, score) in [("Ann", 9), ("Ben", 7)] {
    print("\(name) scored \(score)")
}

4️⃣ Returning Multiple Values

A function can return a tuple to hand back several related results at once — no extra type required. The caller reads them by label or decomposes them.

// Tuples let a function return MULTIPLE values at once.
func minMax(_ numbers: [Int]) -> (min: Int, max: Int) {
    var lo = numbers[0]
    var hi = numbers[0]
    for n in numbers {
        if n < lo { lo = n }
        if n > hi { hi = n }
    }
    return (lo, hi)                 // return a tuple
}

let result = minMax([3, 8, 1, 6])
print("min = \(result.min)")        // min = 1   (access by label)
print("max = \(result.max)")        // max = 8

// Or decompose the returned tuple directly:
let (lowest, highest) = minMax([5, 2, 9])
print("\(lowest)..\(highest)")      // 2..9

Your turn. Fill in the blanks, then run it and check the output.

// 🎯 YOUR TURN — replace each ___ then run it in SwiftFiddle.

// 1) Make a NAMED tuple describing a book: title (String) and pages (Int).
let book = (title: "Swift", pages: ___)   // 👉 e.g. 320

// 2) Print the title using its label.
print(book.___)                            // 👉 replace ___ with title

// 3) DECOMPOSE the tuple into two constants, ignoring the title with _.
let (_, count) = ___                       // 👉 replace ___ with book
print("Pages: \(count)")

// ✅ Expected output (pages = 320):
//    Swift
//    Pages: 320

Pro Tips

Common Errors (and the fix)

📋 Quick Reference

TaskCodeResult
Createlet t = ("Ada", 36)(String, Int)
By positiont.0first element
Named(x: 3, y: 5).x3
Decomposelet (a, b) = ta, b separately
Ignorelet (_, b) = tskip first
Return many-> (min: Int, max: Int)two values

Mini-Challenge: Divide with Remainder

Build it, run it, and check your output against the example in the comments.

// 🎯 MINI-CHALLENGE: Divide with remainder
// 1. Write a function divide(_ a: Int, by b: Int) -> (quotient: Int, remainder: Int)
//    that returns (a / b, a % b) as a NAMED tuple.
// 2. Call it with divide(17, by: 5) and store the result.
// 3. Print "17 / 5 = 3 remainder 2" using the .quotient and .remainder labels.
// 4. Then decompose a second call let (q, r) = divide(20, by: 6) and print q and r.
//
// ✅ Example output:
//    17 / 5 = 3 remainder 2
//    20 / 6 = 3 r 2

// your code here

🎉 Lesson Complete!

Practice quiz

What is a tuple in Swift?

  • An array of one type
  • A key-value map
  • A group of multiple values combined into one compound value
  • A kind of optional

Answer: A group of multiple values combined into one compound value. A tuple groups several values, which can be of different types, into one value.

Can the elements of a tuple have different types?

  • Yes, e.g. (Int, String)
  • No, they must match
  • Only two same-type values
  • Only with classes

Answer: Yes, e.g. (Int, String). Tuple members may each have a different type.

How do you access the first element of an unnamed tuple `t`?

  • t[0]
  • t.first
  • t(0)
  • t.0

Answer: t.0. Unnamed tuple members are accessed by position with .0, .1, etc.

Given let point = (x: 3, y: 5), how do you read the x value?

  • point.0 only
  • point.x
  • point["x"]
  • point->x

Answer: point.x. Named tuple elements are accessed by their label, e.g. point.x.

What does `let (a, b) = (1, 2)` do?

  • Decomposes the tuple, binding a=1 and b=2
  • Creates a dictionary
  • Raises an error
  • Creates an array

Answer: Decomposes the tuple, binding a=1 and b=2. This is tuple decomposition: each element is bound to a name.

What is a common use of tuples?

  • Storing thousands of items
  • Replacing classes
  • Returning multiple values from a function
  • Looping forever

Answer: Returning multiple values from a function. Tuples let a function return several related values at once.

If a function returns (min: Int, max: Int), how do you read the max?

  • result.maximum
  • result.1 or result.max
  • result[1].max
  • result->max

Answer: result.1 or result.max. You can use the label result.max or the position result.1.

What is the index of the second element of an unnamed tuple?

  • .2
  • [1]
  • .second
  • .1

Answer: .1. Positions are zero-based, so the second element is .1.

Can you ignore a tuple element during decomposition?

  • No
  • Yes, using an underscore _ in its place
  • Only the first one
  • Only named ones

Answer: Yes, using an underscore _ in its place. Use _ to ignore an element you don't need, e.g. let (_, y) = point.

Are tuples best for large, long-lived data models?

  • Yes, always prefer them
  • Yes, they replace structs
  • No — for richer/persisted data, prefer a struct
  • Only for networking

Answer: No — for richer/persisted data, prefer a struct. Tuples are great for lightweight grouping; structs are better for substantial models.

Continue this course

Frequently asked questions

What is a tuple and when should I use one?

A tuple groups several values — possibly of different types — into one compound value, like (Int, String). They're perfect for lightweight, temporary grouping: returning two related values from a function, pairing a key with a value in a loop, or bundling coordinates. For richer, longer-lived data with behaviour, prefer a struct.

How do I access tuple elements?

By position using dot-number syntax: tuple.0, tuple.1, and so on (zero-based). If you give the elements names when you create the tuple — for example (x: 3, y: 5) — you can access them by label too: point.x. Named tuples are far more readable and still support positional access.

What is tuple decomposition?

Decomposition unpacks a tuple's elements into separate named constants or variables in one statement: let (code, message) = (200, "OK") binds code to 200 and message to "OK". You can ignore parts you don't need with an underscore, e.g. let (_, message) = response. It reads cleanly and avoids repeated .0/.1 access.

How does a function return multiple values?

Make its return type a tuple. For example -> (min: Int, max: Int) returns two named integers. The caller can read them by label (result.min) or decompose the result directly with let (lo, hi) = result. This is the idiomatic Swift way to hand back several related results without defining a whole new type.

Should I use a tuple or a struct?

Use a tuple for small, throwaway groupings that live briefly and have no behaviour. Reach for a struct when the data is meaningful across your program, needs methods, conforms to protocols, or will be stored and passed around widely — a named type with documented properties is clearer and more maintainable than a sprawling tuple.

Related lessons