《Rust Programming Language》- 04 - Enums and Pattern Matching
2022-12-25
fn main() { enum IpAddrKind { V4, V6, } struct IpAddr { kind: IpAddrKind, address: String, } let home = IpAddr { kind: IpAddrKind::V4, address: String::from("127.0.0.1"), }; let loopback = IpAddr { kind: IpAddrKind::V6, address: String::from("::1"), }; }
And you can put data directly to the enum values:
// this snippet is simpler version of the above snippet fn main() { enum IpAddr { V4(String), V6(String), } let home = IpAddr::V4(String::from("127.0.0.1")); let loopback = IpAddr::V6(String::from("::1")); }
There’s another advantage to using an enum rather than a struct: each variant can have different types and amounts of associated data.
fn main() { enum IpAddr { V4(u8, u8, u8, u8), V6(String), } let home = IpAddr::V4(127, 0, 0, 1); let loopback = IpAddr::V6(String::from("::1")); }
Example from Rust std lib:
#![allow(unused)] fn main() { struct Ipv4Addr { // --snip-- } struct Ipv6Addr { // --snip-- } enum IpAddr { V4(Ipv4Addr), V6(Ipv6Addr), } }
And another example:
enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } // above snippet is equivalent to below snippet struct QuitMessage; // unit struct struct MoveMessage { x: i32, y: i32, } struct WriteMessage(String); // tuple struct struct ChangeColorMessage(i32, i32, i32); // tuple struct
fn main() { enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } impl Message { // add method for Enum `Message` fn call(&self) { // method body would be defined here } } let m = Message::Write(String::from("hello")); m.call(); }
enum Option<T> { None, Some(T), }
Rust does not have null
type, instead use Option
.
Compiler will make sure we handle that case before using the value.
fn main() { let x: i8 = 5; let y: Option<i8> = Some(5); let sum = x + y; // Error: no implementation for `i8 + Option<i8>` }
match
seems very similar to an expression used with if, but there’s a big difference: with if, the expression needs to return a Boolean value, but here, it can return any type. The type of coin in this example is the Coin enum that we defined on the first line.
enum Coin { Penny, Nickel, Dime, Quarter, } fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => 1, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } }
#[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) => { // Works like a method // `{:?}` uses debug trait for output println!("State quarter from {:?}!", state); 25 } } } fn main() { value_in_cents(Coin::Quarter(UsState::Alaska)); }
Matches must cover every possible cases.
fn plus_one(x: Option<i32>) -> Option<i32> { match x { // All possible cases must be covered due to Option<T> type Some(i) => Some(i + 1), None => None, } }
let x = 5; match x { 1 => println!("x is 1"), 2 => println!("x is 2"), // Catch All other => println!("x is something else: {}", other), }
Differences: No Binding for this case.
let value = 5; match value { 1 => println!("One"), 2 => println!("Two"), _ => println!("Other value"), }
fn main() { let config_max = Some(3u8); // Original match pattern match config_max { Some(max) => println!("The maximum is configured to be {}", max), _ => (), } /* Shorthand with `if let` Format: if let [arm] = [variable] { ... } else { ... } */ if let Some(max) = config_max { println!("The maximum is configured to be {}", max); } }
关于本文
文章标题 | 《Rust Programming Language》- 04 - Enums and Pattern Matching |
发布日期 | 2022-12-25 |
文章分类 | Tech |
相关标签 | #Rust |
留言板
PLACE_HOLDER
PLACE_HOLDER
PLACE_HOLDER
PLACE_HOLDER