RustArena

Step 7 of 7

Choosing how to pass a value

You now have four ways to hand a value to a function. Choosing well is most of what "idiomatic Rust" means for function signatures:

The function... Parameter Example
only reads the value &T fn total(items: &Vec<u32>) -> u32
changes the value in place &mut T fn restock(items: &mut Vec<u32>, n: u32)
keeps the value, or uses it up T (move) fn archive(report: String)
gets a small Copy value T (copy) fn is_adult(age: u32) -> bool
creates new data returns an owned T fn make_label(...) -> String

Here's a bank account that uses all of them:

fn print_statement(owner: &String, history: &Vec<i64>) {
    let mut balance = 0;
    for amount in history {
        balance += amount;
    }
    println!("{}: {} transactions, balance {}", owner, history.len(), balance);
}

fn deposit(history: &mut Vec<i64>, amount: i64) {
    history.push(amount);
}

fn close_account(owner: String, history: Vec<i64>) -> String {
    format!("closed {}'s account after {} transactions", owner, history.len())
}

fn main() {
    let owner = String::from("Ferris");
    let mut history = vec![100];
    deposit(&mut history, 50);
    deposit(&mut history, -30);
    print_statement(&owner, &history);
    let receipt = close_account(owner, history);
    println!("{}", receipt);
}
Ferris: 3 transactions, balance 120
closed Ferris's account after 3 transactions

Workplace notes

Common mistakes

Your task

Every function below takes ownership of its arguments, which forces main to .clone() everything. Refactor: give each function the least access it needs (& to read, &mut to change, plain u32s stay as they are), update the calls, and remove every .clone(). restock should change the vector in place and return nothing. The output must stay:

total: 215
bolts x120
nuts x80
gears x50
total: 250

Challenge 2

Fill in each function's parameter type: count_urgent only reads the task list, add changes it, and archive uses it up for good. The program should print:

urgent tasks: 1
archived 3 tasks

Challenge 3

Write transfer, which moves amount from one balance to another. If from holds less than amount, change nothing and return false; otherwise move the money and return true.

The borrowing rules make one mistake impossible: nobody can call transfer(&mut a, &mut a, 10), because that would be two &mut to the same balance (E0499).

Previous: No dangling references