What is Default in Rust?
Tags: rust, tutorial, programming
Published: 2023-01-15 13:19:15

## What is Default?
Each types returns default values from `default()`.

For example
```rust
fn main() {
    let s = String::default();
    println!("String: {}", s);

    let int = i32::default();
    println!("Integer: {}", int);

    let str: &str = Default::default();
    println!("&str: {}", str);
}
```

Run this code
```
$ cargo run

String: 
Integer: 0
&str: 
```
Each type implements `default()`, so the value defined by `{TypeName}::default()` is returned.

Details of `default()` implemented for each type can be found in the official documentation.
For example, if you look at `String`, it says it returns `String::new()`.
```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
impl const Default for String {
    /// Creates an empty `String`.
    #[inline]
    fn default() -> String {
        String::new()
    }
}
```

https://doc.rust-lang.org/src/alloc/string.rs.html#2263


## Use #[derive(Default)] to implement Default
Normally, when inserting a value into a generated object, it is written as follows.
```rust
struct Product {
    name: String,
    price: f64,
}

fn main() {
    let product = Product {
        name: "".to_string(),
        price: 0.0,
    };
    println!("{} price ${}", product.name, product.price);
}

# $ cargo run
# Name: , Price $0
```
You need to put in a value for each of them as shown above. This would be fine, but in an actual product, there will be more attributes, so it is a pain to put in a value for one by one.

Let's use `Default::default();` as described above.
```rust
fn main() {
    let product : Product= Default::default();
    println!("Name: {}, Price ${}", product.name, product.price);
}
```

Building returns following error.
```
$ cargo run
   Compiling app v0.1.0 (/Users/s14960/ghq/github.com/yuki0418/rust-practice/app)
error[E0277]: the trait bound `Product: Default` is not satisfied
 --> src/main.rs:7:28
  |
7 |     let product : Product= Default::default();
  |                            ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Product`
  |
help: consider annotating `Product` with `#[derive(Default)]`
  |
1 | #[derive(Default)]
  |

For more information about this error, try `rustc --explain E0277`.
error: could not compile `app` due to previous error
```
As you can see, the reason of this error is that Default is not implemented for Product.

Let implement `Default` to `Product`.
```rust
#[derive(Default)] // <- Use Default.
struct Product {
    name: String,
    price: f64,
}

fn main() {
    let product : Product= Default::default();
    println!("Name: {}, Price ${}", product.name, product.price);
    
    let named_product = Product {
        name: "Coffee".to_string(),
        ..Default::default()
    };
    println!("Name: {}, Price ${}", named_product.name, named_product.price);
}
```

Then run this code.
```
% $ cargo run
Name: , Price $0
```
It contains the value returned by `default()` implemented in each `String` and `f64`.

## Implement default() to Product
You can define a custom default value with implementing `default()` to a struct.
```rust
// Remove #[derive(Default)]
struct Product {
    name: String,
    price: f64,
}

// Implement Default
impl Default for Product {
    fn default() -> Self {
        Self {
            name: "Default name".to_string(),
            price: 999.0,
        }
    }
}

fn main() {
    let product= Product::default();
    // let product : Product = Default::default(); <- Return same result 
    println!("Name: {}, Price ${}", product.name, product.price);
}
```
Run this code.
```
$ cargo run
Name: Default name, Price $999
```
It returns default values which just implemented before.

## Implement Default to enum
You can implement `default` to enum as well.
```rust
#[derive(Default, Debug)] // Need Debug for `println` for logging.
enum Fruit {
    #[default]
    Apple,
    Banana,
    Orange,
}

fn main() {
    let fruit = Fruit::default();
    println!("{:?}", fruit);

    let banana = Fruit::Banana;
    println!("{:?}", banana);
}
```
The result is below.
```
$ cargo run
Apple
Banana
```

## How be used in real product
Let check how Default is used in real life products.

### actix-web head type
Let check actix-web which is poplar library for web in Rust. 
Request has `RequestHead`.
```rust
#[derive(Debug, Clone)]
pub struct RequestHead {
    pub method: Method,
    pub uri: Uri,
    pub version: Version,
    pub headers: HeaderMap,
    pub peer_addr: Option<net::SocketAddr>,
    flags: Flags,
}

impl Default for RequestHead {
    fn default() -> RequestHead {
        RequestHead {
            method: Method::default(),
            uri: Uri::default(),
            version: Version::HTTP_11,
            headers: HeaderMap::with_capacity(16),
            peer_addr: None,
            flags: Flags::empty(),
        }
    }
}
```
As you can see, it returns default values for each types.
`HTTP_11` is defined for `version` as the default value.

Reference: 
https://github.com/actix/actix-web/blob/3200de3f34b21f65bf84d7b04ba118f03d808f02/actix-http/src/requests/head.rs

## Conclusion
It is easy to implement the definition of the Default value in a `struct` so that when you use it, all you have to do is execute the implemented `default()`.

## Official document
https://doc.rust-lang.org/std/default/trait.Default.html


```rust
pub trait Default: Sized {
    fn default() -> Self;
}
```