RustArena

Step 3 of 6

Building structs with shorthand and update syntax

Building structs in functions is so common that Rust has two shortcuts for it.

Field init shorthand

When a variable has the same name as the field, write the name once: price_cents instead of price_cents: price_cents. This is the field init shorthand. Clippy flags the long form (redundant_field_names), so in real code you'll see the short one everywhere.

Struct update syntax

..other at the end of an instance means "every field I didn't list comes from other". This is struct update syntax, handy for "the same, but with these changes":

struct Settings {
    player_name: String,
    volume: u8,
    music: bool,
    difficulty: u8,
}

fn default_settings(player_name: String) -> Settings {
    Settings {
        player_name,
        volume: 70,
        music: true,
        difficulty: 2,
    }
}

fn main() {
    let base = default_settings(String::from("Ferris"));
    let hard = Settings {
        difficulty: 5,
        music: false,
        ..base
    };
    println!("{} plays at difficulty {}", hard.player_name, hard.difficulty);
    println!("volume {}, music {}", hard.volume, hard.music);
}
Ferris plays at difficulty 5
volume 70, music false

The update syntax moves

..base works like assignment: Copy fields (numbers, bool) are copied, but a String field is moved out of base. After that line, base.player_name is gone, while base.volume is still fine:

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

fn main() {
    let a = Player { name: String::from("Ferris"), score: 10 };
    let b = Player { score: 99, ..a };
    println!("{} {}", b.name, b.score);
    println!("{}", a.name);
}
error[E0382]: borrow of moved value: `a.name`

If you still need a, give the moved fields explicitly (name: a.name.clone()), or just don't use a afterwards. Often the struct you update from is a temporary that's thrown away anyway.

Your task

Write fn new_item(name: &str, price_cents: u32) -> Item that returns an Item with that name and price, and a quantity of 0. Use the field init shorthand for price_cents.

Challenge 2

Write fn with_price(item: Item, price_cents: u32) -> Item. It returns the same item with a new price. Use struct update syntax (..item) for the fields that stay the same, and the shorthand for price_cents.

Challenge 3

Write two functions for a game:

Previous: Changing structs and passing them around Next: Printing structs with Debug