Skip to content
AgileLogics
6 min read

Tuples & Arrays

Prerequisites: Strings: String vs &str

Tuples and arrays are Rust's two built-in compound types. Both have a fixed length that never changes.

Syntax

let person: (&str, i32, bool) = ("Ada", 36, true); // tuple
let name = person.0;                               // access by position
let (n, age, active) = person;                     // destructuring

let scores: [i32; 3] = [90, 85, 77];               // array: [type; length]
let zeros = [0; 5];                                // [0, 0, 0, 0, 0]
let first = scores[0];                             // access by index

Tuples group a fixed number of values that can have different types. Access fields with .0, .1, and so on, or unpack them all at once with a let (a, b, c) = ... pattern. Tuples are an easy way to return several values from a function. The empty tuple () is called the unit type — it's what functions without a return value return.

Arrays hold a fixed number of values of the same type. The length is part of the type: [i32; 3] and [i32; 4] are different types. Arrays live on the stack. When you need a list that can grow, use a vector (next lesson).

Indexing is checked: an out-of-range index stops the program with a panic instead of reading random memory.

Example

fn min_max(values: [i32; 5]) -> (i32, i32) {
    let mut min = values[0];
    let mut max = values[0];
    for v in values {
        if v < min {
            min = v;
        }
        if v > max {
            max = v;
        }
    }
    (min, max)
}

fn main() {
    let person = ("Ada", 36, true);
    println!("{} is {}", person.0, person.1);

    let (name, age, active) = person;
    println!("{name}, {age}, active: {active}");

    let point = (3, -2);
    let (x, y) = point;
    println!("x = {x}, y = {y}");

    let scores = [90, 85, 77, 62, 98];
    println!("first: {}, last: {}", scores[0], scores[scores.len() - 1]);
    println!("{} scores: {scores:?}", scores.len());

    let (low, high) = min_max(scores);
    println!("low: {low}, high: {high}");

    let mut grid = [[0; 3]; 2];
    grid[1][2] = 7;
    println!("{grid:?}");
}

Expected output

Ada is 36
Ada, 36, active: true
x = 3, y = -2
first: 90, last: 98
5 scores: [90, 85, 77, 62, 98]
low: 62, high: 98
[[0, 0, 0], [0, 0, 7]]

Common mistakes

  • Indexing past the end with a constant index. The compiler catches it:
let numbers = [1, 2, 3];
println!("{}", numbers[5]);
error: this operation will panic at runtime

followed by index out of bounds: the length is 3 but the index is 5. If the index is only known at runtime, the program compiles and panics when it runs instead.

  • Trying to push onto an array. Arrays can't grow; use a Vec.
  • Mixing types in an array, like [1, "two"]. Every element must have the same type — use a tuple if you need mixed types.

Practice

Write a function stats(values: [f64; 4]) -> (f64, f64) that returns the sum and the average of four numbers. Call it with [2.0, 4.0, 6.0, 8.0] and print Sum: 20, average: 5.

Show solution
fn stats(values: [f64; 4]) -> (f64, f64) {
    let mut sum = 0.0;
    for v in values {
        sum += v;
    }
    (sum, sum / values.len() as f64)
}

fn main() {
    let (sum, average) = stats([2.0, 4.0, 6.0, 8.0]);
    println!("Sum: {sum}, average: {average}");
}