What is Default in Rust?
Yuki Ishii
Posted on January 15, 2023
What is Default?
Each types returns default values from default()
.
For example
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.
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.
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
.
#[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.
// 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.
#[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
.
#[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.
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
pub trait Default: Sized {
fn default() -> Self;
}
Posted on January 15, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.