Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Borrowing and unpacking while iterating

Borrow a list when a helper needs to inspect or mutate it without taking ownership:

def total(values: &list[i64]) -> Result[i64, OverflowError[i64]]:
    mut result = 0
    for value in values:
        result = result + value
    Ok(result)

def add(values: &mut list[i64], value: i64) -> Result[(), AllocError]:
    values.append(value)?
    Ok(())

def main() -> Result[(), AllocError | IoError | OverflowError[i64]]:
    mut numbers = [1, 2]?
    print(total(numbers)?)?
    add(&mut numbers, 3)?
    print(numbers)?
    Ok(())
3
[1, 2, 3]

Unpack a tuple in a loop

def measurement() -> (i64, str):
    (42, "cm")

def main() -> Result[(), AllocError | IoError]:
    value, unit = measurement()
    print(value)?
    print(unit)?
    for number, word in [(1, "one"), (2, "two")]?:
        print((number, word))?
    print((3, "three"))?
    Ok(())
42
cm
(1, "one")
(2, "two")
(3, "three")

Unpacking a borrowed list keeps the list and borrows each component of the current tuple in place: in for number, word in &pairs, number is a &i64 and word a &str. Over &mut pairs, the names are &mut references, so the loop can change the tuples:

def main() -> Result[(), AllocError | IoError | OverflowError[i64]]:
    mut pairs = [(1, "one"), (2, "two")]?
    for number, _ in &mut pairs:
        *number *= 10
    for number, word in &pairs:
        print(*number, word)?
    print(pairs)?
    Ok(())
10 one
20 two
[(10, "one"), (20, "two")]

The names borrow different components, so both can be passed as &mut arguments to one call:

def swap(a: &mut i64, b: &mut i64) -> ():
    t = *a
    *a = *b
    *b = t

def main() -> Result[(), AllocError | IoError]:
    mut pairs = [(1, 2), (3, 4)]?
    for low, high in &mut pairs:
        swap(low, high)
    print(pairs)?
    Ok(())
[(2, 1), (4, 3)]

Tuple targets can nest. Each name still borrows its own component when the source is borrowed:

def main() -> Result[(), AllocError | IoError | OverflowError[i64]]:
    mut rows = [((1, 2), "point")]?
    x = 99
    for (x, y), _ in &mut rows:
        *x += 10
        *y += 20
    print(rows)?
    print(x)?
    Ok(())
[((11, 22), "point")]
99

The loop’s x is a new binding to the borrowed component. The outer x remains available after the loop.