--- date: 20200902 id: b95f09af-2cd0-46f2-872e-3cb542d2b2e9 title: Rust enums --- # Basics Rust also supports [enums](https://doc.rust-lang.org/rust-by-example/custom_types/enum.html). ``` rust use std::fmt::Debug; #[derive(Debug)] enum Message { Write(String), } fn main() { let m = Message::Write(String::from("Hello!")); println!("{:?}", m) } ``` # Methods As with [structs](20200831193417-structs), methods can be defined as well: ``` rust use std::fmt::Debug; #[derive(Debug)] enum Message { Write(String), } impl Message { fn call(&self) { println!("tralala"); println!("{:?}", self) } } fn main() { let m = Message::Write(String::from("Hello!")); m.call(); } ``` # Standard library enums ## Option Instead of \`null\` Rust has the [Option](https://doc.rust-lang.org/std/option/enum.Option.html) enum built in: ``` rust fn main() { let some_number = Some(5); let some_string = Some("a string"); let absent_number: Option = None; } ``` The cool thing about using Option is that \`Option\\` and \`T\` are different types, therefore the programmer has to define if NULL is acceptable beforehand. The following won't run: ``` rust fn main() { let x: i8 = 5; let y: Option = Some(5); let sum = x + y; } ``` Huzzah, No more having to worry about incorrectly assuming a not null value! # Match control flow operator Think of \`switch\`, but for enums. ``` rust enum Coin { Penny, Nickel, Dime, Quarter, } fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => { println!("Lucky penny!"); 1 } Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } } fn main() {} ``` ## Patterns that bind to values Another useful feature of match arms is that they can bind to the parts of the values that match the pattern. This is how we can extract values out of enum variants. ``` rust #[derive(Debug)] enum UsState { Alabama, Alaska, // --snip-- } enum Coin { Penny, Nickel, Dime, Quarter(UsState), } fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => 1, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter(state) => { println!("State quarter from {:?}!", state); 25 } } } fn main() { value_in_cents(Coin::Quarter(UsState::Alaska)); } ``` ## Matching with Option\ \`match\` also plays nice with \`Option\\`: ``` rust fn main() { fn plus_one(x: Option) -> Option { match x { None => None, Some(i) => Some(i + 1), } } let five = Some(5); let six = plus_one(five); let none = plus_one(None); } ``` ## The \_ Placeholder Rust also has a pattern we can use when we don’t want to list all possible values: ``` rust fn main() { let some_u8_value = 0u8; match some_u8_value { 1 => println!("one"), 3 => println!("three"), 5 => println!("five"), 7 => println!("seven"), _ => (), } } ``` ## if let syntax suger ``` rust fn main() { let some_u8_value = Some(0u8); match some_u8_value { Some(3) => println!("three"), _ => (), } } ``` is the same as ``` rust fn main() { let some_u8_value = Some(0u8); if let Some(3) = some_u8_value { println!("three"); } } ``` and ``` rust #[derive(Debug)] enum UsState { Alabama, Alaska, // --snip-- } enum Coin { Penny, Nickel, Dime, Quarter(UsState), } fn main() { let coin = Coin::Penny; let mut count = 0; match coin { Coin::Quarter(state) => println!("State quarter from {:?}!", state), _ => count += 1, } } ``` is the same as ``` rust #[derive(Debug)] enum UsState { Alabama, Alaska, // --snip-- } enum Coin { Penny, Nickel, Dime, Quarter(UsState), } fn main() { let coin = Coin::Penny; let mut count = 0; if let Coin::Quarter(state) = coin { println!("State quarter from {:?}!", state); } else { count += 1; } } ```