Variants can hold data
#![allow(unused)] fn main() { enum Status { ToDo, InProgress, Done, } }
Our Status
enum is what's usually called a C-style enum.
Each variant is a simple label, a bit like a named constant. You can find this kind of enum in many programming
languages, like C, C++, Java, C#, Python, etc.
Rust enums can go further though. We can attach data to each variant.
Variants
Let's say that we want to store the name of the person who's currently working on a ticket.
We would only have this information if the ticket is in progress. It wouldn't be there for a to-do ticket or
a done ticket.
We can model this by attaching a String
field to the InProgress
variant:
#![allow(unused)] fn main() { enum Status { ToDo, InProgress { assigned_to: String, }, Done, } }
InProgress
is now a struct-like variant.
The syntax mirrors, in fact, the one we used to define a struct—it's just "inlined" inside the enum, as a variant.
Accessing variant data
If we try to access assigned_to
on a Status
instance,
#![allow(unused)] fn main() { let status: Status = /* */; // This won't compile println!("Assigned to: {}", status.assigned_to); }
the compiler will stop us:
error[E0609]: no field `assigned_to` on type `Status`
--> src/main.rs:5:40
|
5 | println!("Assigned to: {}", status.assigned_to);
| ^^^^^^^^^^^ unknown field
assigned_to
is variant-specific, it's not available on all Status
instances.
To access assigned_to
, we need to use pattern matching:
#![allow(unused)] fn main() { match status { Status::InProgress { assigned_to } => { println!("Assigned to: {}", assigned_to); }, Status::ToDo | Status::Done => { println!("Done"); } } }
Bindings
In the match pattern Status::InProgress { assigned_to }
, assigned_to
is a binding.
We're destructuring the Status::InProgress
variant and binding the assigned_to
field to
a new variable, also named assigned_to
.
If we wanted, we could bind the field to a different variable name:
#![allow(unused)] fn main() { match status { Status::InProgress { assigned_to: person } => { println!("Assigned to: {}", person); }, Status::ToDo | Status::Done => { println!("Done"); } } }
Exercise
The exercise for this section is located in 05_ticket_v2/03_variants_with_data