Enums and Option
A struct has all of its fields at once. An enum is exactly one of its variants at a time.
Defining enums
List the variants inside the braces. Name a variant with the enum name and ::.
enum Dir { North, South,}let d = Dir::North;A Dir is always North or South, never both.
Variants with data
Each variant can carry its own data. A variant can look like a tuple, look like a struct, or hold nothing.
enum Shape { Circle(f64), Rect { w: f64, h: f64 }, Empty,}let s = Shape::Rect { w: 2.0, h: 3.0 };All three are the same type, Shape, so they can share one Vec<Shape>.
Option
Rust has no null. A value that might be missing has type Option<T>. It is an enum with two variants: Some(value) and None.
let found: Option<i32> = Some(5);let empty: Option<i32> = None;You don't write Option:: before Some and None. You can't use an Option<i32> as an i32; deal with None first. A bare let x = None; is E0282: Rust can't tell the type, so write Option<i32>.
Option methods
You don't always need a full match.
is_some()andis_none()ask which variant it is.unwrap_or(x)gives the value, orxif it isNone.map(f)runsfon the value inside aSomeand leavesNonealone.unwrap()gives the value, but crashes onNone.expect("msg")is the same, with your message.
fn double(n: i32) -> i32 { n * 2 }let a = Some(4).map(double); // Some(8)let b: Option<i32> = None;let c = b.unwrap_or(0); // 0Methods on enums
Enums can have impl blocks, just like structs. &self, &mut self, self and associated functions all work the same way.
#[derive(Debug)]enum Door { Open, Shut }impl Door { fn new() -> Self { Door::Shut } fn open(&mut self) { *self = Door::Open; }}*self is the value itself, so *self = Door::Open; swaps in a new variant. To act differently for each variant, you need match (next unit).
Remember
- An enum value is one variant at a time.
- Write variants as
Enum::Variant. - Use
Option<T>instead of null. unwrap_orgives a safe fallback forNone.