RustArena

Step 2 of 6

Changing structs and passing them around

Like every variable in Rust, an instance is immutable unless you say mut. With let mut, you can change any field with =, += and friends. Mutability belongs to the whole instance: Rust has no way to mark just one field as mut.

Structs and functions

A struct follows the ownership rules you already know. Pass &Player to a function that only reads it, and &mut Player to a function that changes it. Through a reference you still write account.balance: Rust follows the reference for you, so there's no need for (*account).balance.

struct Account {
    owner: String,
    balance: i64,
}

fn deposit(account: &mut Account, amount: i64) {
    account.balance += amount;
}

fn report(account: &Account) {
    println!("{}: {}", account.owner, account.balance);
}

fn main() {
    let mut acct = Account {
        owner: String::from("Ada"),
        balance: 100,
    };
    report(&acct);
    deposit(&mut acct, 50);
    acct.balance -= 30;
    report(&acct);
}
Ada: 100
Ada: 120

Functions can also return a struct. That's how you'll usually build one: a function that takes a few values and fills in the rest.

struct Account {
    owner: String,
    balance: i64,
}

fn open_account(owner: &str) -> Account {
    Account {
        owner: owner.to_string(),
        balance: 0,
    }
}

fn main() {
    let acct = open_account("Grace");
    println!("{} starts with {}", acct.owner, acct.balance);
}
Grace starts with 0

Common mistakes

struct Player {
    name: String,
    score: u32,
}

fn main() {
    let p = Player { name: String::from("Ferris"), score: 10 };
    p.score += 5;
    println!("{} {}", p.name, p.score);
}
error[E0594]: cannot assign to `p.score`, as `p` is not declared as mutable

Your task

Write fn level_up(hero: &mut Hero). It adds 1 to level, adds 10 to max_hp, and then fully heals the hero: hp becomes the new max_hp. The name doesn't change.

Challenge 2

Write fn take_damage(hero: &mut Hero, amount: u32). It lowers hp by amount, but hp never goes below 0 (remember: subtracting past zero on a u32 panics in a debug build). No other field changes.

Challenge 3

Write fn transfer(from: &mut Account, to: &mut Account, amount: i64) from scratch. It moves amount from from's balance to to's balance. If from has less than amount, nothing changes at all. Owners never change.

Previous: Grouping data with a struct Next: Building structs with shorthand and update syntax