BBuzzard

A tuple groups a fixed number of values of mixed types: (i32, &str). Read a field with a dot and an index, pair.0, or destructure the whole thing with let. () is the unit tuple, the type of an expression with no useful value. A one-element tuple needs a trailing comma: (1,).

An array has a fixed length that is part of its type: [i32; 3]. All elements share one type. [0; 4] repeats a value. Arrays live inline (on the stack for a local), and out-of-range indexing panics. &a[1..] borrows part of an array as a slice.

Building, reading, and destructuring tuples

fn demo_tuples() {
    println!("-- tuples --");

    let pair = (7, "ok");
    println!("{} {}", pair.0, pair.1);

    let (n, label) = pair;
    println!("unpacked {n} {label}");

    let nested = ((1, 2), [3, 4], "five");
    let ((a, _), [_, d], e) = nested;
    println!("nested {} picked {a} {d} {e}", (nested.0).1);

    let single = (1,);

    // Without the comma, (1) is just 1 in parentheses.
    println!("single {single:?} len-one tuple field {}", single.0);

    let unit = ();
    println!("unit {unit:?}");
}

Tuples as multiple return values, and swapping

fn min_max(nums: &[i32]) -> (i32, i32) {
    let mut lo = nums[0];
    let mut hi = nums[0];
    for &n in nums {
        lo = lo.min(n);
        hi = hi.max(n);
    }

    (lo, hi)
}

fn demo_tuple_returns() {
    println!("-- tuple returns --");

    let (lo, hi) = min_max(&[4, -2, 9, 3]);
    println!("lo {lo} hi {hi}");

    let mut a = 1;
    let mut b = 2;
    (a, b) = (b, a);
    println!("swapped a {a} b {b}");

    // Tuples compare element by element, left to right.
    println!("(1, 9) < (2, 0)? {}", (1, 9) < (2, 0));
    println!("(\"a\", 2) == (\"a\", 3)? {}", ("a", 2) == ("a", 3));
}

Building and reading arrays

fn demo_arrays() {
    println!("-- arrays --");

    let a: [i32; 3] = [1, 2, 3];
    let zeros = [0; 4];
    let grid = [[0u8; 3]; 2];
    println!("first {} len {} zeros {zeros:?} grid {grid:?}", a[0], a.len());

    let mut b = a;
    b[0] = 100;
    println!("copy changed {b:?}, original {a:?}");

    // get returns None instead of panicking on a bad index.
    println!("get {:?} {:?}", a.get(1), a.get(10));

    // let oops = a[10];
    // error: this operation will panic at runtime: index out of bounds

    println!("contains 2? {} iter sum {}", a.contains(&2), a.iter().sum::<i32>());
    let squares: [u32; 5] = std::array::from_fn(|i| (i as u32) * (i as u32));
    println!("from_fn {squares:?}");

    let doubled = a.map(|n| n * 2);
    println!("map {doubled:?}");
}

Arrays and slices

fn demo_array_slices() {
    println!("-- array slices --");

    let a = [10, 20, 30, 40, 50];
    let view: &[i32] = &a[1..4];
    println!("view {view:?} len {}", view.len());
    println!("first {:?} last {:?}", a.first(), a.last());

    let (left, right) = a.split_at(2);
    println!("split {left:?} {right:?}");

    for pair in a.windows(2) {
        print!("{} ", pair[1] - pair[0]);
    }

    println!();
    for chunk in a.chunks(2) {
        print!("{chunk:?} ");
    }

    println!();

    let mut m = [3, 1, 2];
    m.sort();
    m.reverse();
    println!("sorted desc {m:?}");
}

Iterating over arrays

fn demo_array_iteration() {
    println!("-- array iteration --");

    let names = ["ann", "ben", "cy"];
    for name in names {
        print!("{name} ");
    }

    println!();
    for (i, name) in names.iter().enumerate() {
        print!("{i}:{name} ");
    }

    println!();
    let mut nums = [1, 2, 3];
    for n in &mut nums {
        *n *= 10;
    }

    println!("{nums:?}");
}
$ cargo run --bin 04_tuples_arrays
-- tuples --
7 ok
unpacked 7 ok
nested 2 picked 1 4 five
single (1,) len-one tuple field 1
unit ()
-- tuple returns --
lo -2 hi 9
swapped a 2 b 1
(1, 9) < (2, 0)? true
("a", 2) == ("a", 3)? false
-- arrays --
first 1 len 3 zeros [0, 0, 0, 0] grid [[0, 0, 0], [0, 0, 0]]
copy changed [100, 2, 3], original [1, 2, 3]
get Some(2) None
contains 2? true iter sum 6
from_fn [0, 1, 4, 9, 16]
map [2, 4, 6]
-- array slices --
view [20, 30, 40] len 3
first Some(10) last Some(50)
split [10, 20] [30, 40, 50]
10 10 10 10 
[10, 20] [30, 40] [50] 
sorted desc [3, 2, 1]
-- array iteration --
ann ben cy 
0:ann 1:ben 2:cy 
[10, 20, 30]

Full program

04_tuples_arrays/main.rs · 150 lines
View on GitHub
// 04. Tuples and arrays
//
// A tuple groups a fixed number of values of mixed types: (i32, &str). Read a field
// with a dot and an index, pair.0, or destructure the whole thing with let. () is the
// unit tuple, the type of an expression with no useful value. A one-element tuple needs
// a trailing comma: (1,).
//
// An array has a fixed length that is part of its type: [i32; 3]. All elements share
// one type. [0; 4] repeats a value. Arrays live inline (on the stack for a local), and
// out-of-range indexing panics. &a[1..] borrows part of an array as a slice.
//
// Run: cargo run --bin 04_tuples_arrays

// Example 1: building, reading, and destructuring tuples.
fn demo_tuples() {
    println!("-- tuples --");

    let pair = (7, "ok");
    println!("{} {}", pair.0, pair.1);

    let (n, label) = pair;
    println!("unpacked {n} {label}");

    let nested = ((1, 2), [3, 4], "five");
    let ((a, _), [_, d], e) = nested;
    println!("nested {} picked {a} {d} {e}", (nested.0).1);

    let single = (1,);

    // Without the comma, (1) is just 1 in parentheses.
    println!("single {single:?} len-one tuple field {}", single.0);

    let unit = ();
    println!("unit {unit:?}");
}

fn min_max(nums: &[i32]) -> (i32, i32) {
    let mut lo = nums[0];
    let mut hi = nums[0];
    for &n in nums {
        lo = lo.min(n);
        hi = hi.max(n);
    }

    (lo, hi)
}

// Example 2: tuples as multiple return values, and swapping.
fn demo_tuple_returns() {
    println!("-- tuple returns --");

    let (lo, hi) = min_max(&[4, -2, 9, 3]);
    println!("lo {lo} hi {hi}");

    let mut a = 1;
    let mut b = 2;
    (a, b) = (b, a);
    println!("swapped a {a} b {b}");

    // Tuples compare element by element, left to right.
    println!("(1, 9) < (2, 0)? {}", (1, 9) < (2, 0));
    println!("(\"a\", 2) == (\"a\", 3)? {}", ("a", 2) == ("a", 3));
}

// Example 3: building and reading arrays.
fn demo_arrays() {
    println!("-- arrays --");

    let a: [i32; 3] = [1, 2, 3];
    let zeros = [0; 4];
    let grid = [[0u8; 3]; 2];
    println!("first {} len {} zeros {zeros:?} grid {grid:?}", a[0], a.len());

    let mut b = a;
    b[0] = 100;
    println!("copy changed {b:?}, original {a:?}");

    // get returns None instead of panicking on a bad index.
    println!("get {:?} {:?}", a.get(1), a.get(10));

    // let oops = a[10];
    // error: this operation will panic at runtime: index out of bounds

    println!("contains 2? {} iter sum {}", a.contains(&2), a.iter().sum::<i32>());
    let squares: [u32; 5] = std::array::from_fn(|i| (i as u32) * (i as u32));
    println!("from_fn {squares:?}");

    let doubled = a.map(|n| n * 2);
    println!("map {doubled:?}");
}

// Example 4: arrays and slices.
fn demo_array_slices() {
    println!("-- array slices --");

    let a = [10, 20, 30, 40, 50];
    let view: &[i32] = &a[1..4];
    println!("view {view:?} len {}", view.len());
    println!("first {:?} last {:?}", a.first(), a.last());

    let (left, right) = a.split_at(2);
    println!("split {left:?} {right:?}");

    for pair in a.windows(2) {
        print!("{} ", pair[1] - pair[0]);
    }

    println!();
    for chunk in a.chunks(2) {
        print!("{chunk:?} ");
    }

    println!();

    let mut m = [3, 1, 2];
    m.sort();
    m.reverse();
    println!("sorted desc {m:?}");
}

// Example 5: iterating over arrays.
fn demo_array_iteration() {
    println!("-- array iteration --");

    let names = ["ann", "ben", "cy"];
    for name in names {
        print!("{name} ");
    }

    println!();
    for (i, name) in names.iter().enumerate() {
        print!("{i}:{name} ");
    }

    println!();
    let mut nums = [1, 2, 3];
    for n in &mut nums {
        *n *= 10;
    }

    println!("{nums:?}");
}

fn main() {
    demo_tuples();
    demo_tuple_returns();
    demo_arrays();
    demo_array_slices();
    demo_array_iteration();
}