liveBook · Manning

Default

As explained in Learn Rust in a Month of Lunches

Default is the Rust standard trait that defines how to construct a default value for a type.

`Default` is a Rust standard trait for constructing a type’s usual starting value without arguments. Many standard types already implement it: an integer can default to `0`, a `String` to an empty string, and a `bool` to `false`. For your own type, choose values that represent its common or base state. section 15.1

fn main() {
    let default_i8: i8 = Default::default();
    let default_str: String = Default::default();
    let default_bool: bool = Default::default();
 
    println!("'{default_i8}', '{default_str}', '{default_bool}'");
}

These three calls to `Default::default()` produce `0`, an empty string, and `false`. Each variable’s declared type determines which default is constructed. section 15.1

Choose a default for your own type

Implement `Default` when the starting value needs a deliberate choice: ```rust struct DeskMoney(u32); impl Default for DeskMoney { fn default() -> Self { Self(50) } } ``` Now `DeskMoney::default()` contains `50`, not `0`. A default need not mean “empty”; it should mean what makes sense for the type. section 21.1 section 15.1

When every field already implements `Default`, `#[derive(Default)]` can generate the implementation for a struct. To set just one field differently, use struct update syntax with `..Default::default()` for the rest. section 15.1

#[derive(Debug, Default)]
struct Size {
    height: f64,
    length: f64,
    width: f64,
}
 
fn main() {
    let only_height = Size {
        height: 1.0,            #1
        ..Default::default()    #2
    };
    println!("{only_height:?}");
}

The `Size` example sets `height` to `1.0` while its other fields receive their defaults, `0.0`. section 15.1

An enum can derive `Default` by marking its chosen variant with `#[default]`. A calculator, for example, starts with a zero total, an empty number string, and an `Add` operation. section 14.3.2

Implementing the trait also lets the type work with code that requires `Default`. `std::mem::take`, for instance, returns a value while leaving its default behind; taking a `DeskMoney(500)` leaves `DeskMoney(50)`. Defaults can also provide a starting point for changes made through a builder pattern. section 21.1 section 15.1

How Learn Rust in a Month of Lunches covers it

How deep it goes
Works through standard defaults, a manual implementation, derivation, and partial struct construction.
Examples
Uses integers, strings, booleans, custom structs, a calculator enum, and a value replaced through `std::mem::take`.
What it assumes
Assumes basic Rust structs and enums while introducing how to give those types default values.
What you can do after
Build it from scratch with a manual implementation, or apply `#[derive(Default)]` when the type’s fields support it.
How it connects
Connects Default to trait bounds, the builder pattern, struct update syntax, and `std::mem::take`.

Also explained in

Compare how 2 books explain Default →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.