← Rust EnglishChapter 07 of 13

Enums

## Learning Objectives - Define and use enums - Master Option type - Work with Result type - Implement match with enums - Understand pattern matching exhaustiveness ## Defining Enums ### Basic Enum ```rust enum Direction { North, South, East, West, } fn main() { let direction = Direction::North; match direction { Direction::North => println!("Heading north"), Direction::South => println!("Heading south"), Direction::East => println!("Heading east"), Direction::West => println!("Heading west"), } } ``` ### Enum with Data ```rust enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } fn main() { let m1 = Message::Quit; let m2 = Message::Move { x: 10, y: 20 }; let m3 = Message::Write(String::from("hello")); let m4 = Message::ChangeColor(255, 0, 0); } ``` ### Enum with Same Type ```rust enum IpAddrKind { V4, V6, } struct IpAddr { kind: IpAddrKind, address: String, } fn main() { let home = IpAddr { kind: IpAddrKind::V4, address: String::from("127.0.0.1"), }; } ``` ### Enum Methods ```rust impl Message { fn call(&self) { match self { Message::Quit => println!("Quit"), Message::Move { x, y } => println!("Move to ({}, {})", x, y), Message::Write(text) => println!("Write: {}", text), Message::ChangeColor(r, g, b) => println!("Color: {}, {}, {}", r, g, b), } } } fn main() { let m = Message::Write(String::from("hello")); m.call(); } ``` ## Option Enum Option represents optional values (Rust has no null): ```rust enum Option { Some(T), None, } ``` ### Using Option ```rust fn main() { let some_number = Some(5); let no_number: Option = None; if let Some(n) = some_number { println!("Number: {}", n); } match some_number { Some(n) => println!("Number: {}", n), None => println!("No number"), } } ``` ### Option Methods ```rust fn main() { let x = Some(5); // is_some, is_none println!("{}", x.is_some()); // true // unwrap_or let y = x.unwrap_or(0); // 5 // map let z = x.map(|n| n * 2); // Some(10) // unwrap (panics if None) // let y = None.unwrap(); // Panic! // unwrap_or_else let val = Some(5).unwrap_or_else(|| 2 * 3); // 5 let val = (None as Option).unwrap_or_else(|| 2 * 3); // 6 } ``` ### Option with null-like Behavior ```rust fn main() { let numbers = [1, 2, 3, 4, 5]; // Find first even number let first_even = numbers.iter().find(|&&x| x % 2 == 0); match first_even { Some(n) => println!("First even: {}", n), None => println!("No even number"), } // or if let Some(n) = first_even { println!("First even: {}", n); } } ``` ## Result Enum Result represents success or failure: ```rust enum Result { Ok(T), Err(E), } ``` ### Using Result ```rust use std::fs::File; use std::io::Error; fn main() { let file = File::open("hello.txt"); match file { Ok(_) => println!("File opened"), Err(e) => println!("Error: {:?}", e), } } ``` ### Result Methods ```rust fn main() { let x: Result = Ok(5); // is_ok, is_err println!("{}", x.is_ok()); // true // unwrap (panics on Err) // let y = Err("error").unwrap(); // Panic! // unwrap_or let y = x.unwrap_or(0); // 5 // unwrap_or_else let y = Err("error").unwrap_or_else(|_| 0); // 0 // map let doubled = x.map(|n| n * 2); // Ok(10) // map_err let mapped = x.map_err(|e| format!("Error: {}", e)); } ``` ## The ? Operator ```rust use std::fs::File; use std::io; use std::io::Read; fn read_file() -> Result { let mut file = File::open("hello.txt")?; let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents) } ``` ### ? with Option ```rust fn first_word(s: &str) -> Option<&str> { let bytes = s.as_bytes(); for (i, &item) in bytes.iter().enumerate() { if item == b' ' { return Some(&s[0..i]); } } None } fn main() { let text = "hello world"; if let Some(word) = first_word(text) { println!("First word: {}", word); } } ``` ## Match Expressions ### Exhaustive Matching ```rust enum Coin { Penny, Nickel, Dime, Quarter, } fn value_in_cents(coin: Coin) -> u32 { match coin { Coin::Penny => 1, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } } ``` ### Matching with Bound Values ```rust enum Message { Quit, Move { x: i32, y: i32 }, Write(String), } fn main() { let msg = Message::Move { x: 10, y: 20 }; match msg { Message::Quit => println!("Quit"), Message::Move { x, y } => println!("Move to ({}, {})", x, y), Message::Write(text) => println!("Write: {}", text), } } ``` ### Catch-all Patterns ```rust fn main() { let dice_roll = 9; match dice_roll { 3 => println!("3"), 7 => println!("7"), other => println!("{}", other), // Catch all } match dice_roll { 3 => println!("3"), 7 => println!("7"), _ => (), // Ignore remaining } } ``` ### Combining Patterns ```rust fn main() { let c = 'a'; match c { 'a' | 'e' | 'i' | 'o' | 'u' => println!("vowel"), 'a'..='z' => println!("consonant"), _ => println!("other"), } } ``` ## if let Syntax ### Single Pattern ```rust fn main() { let msg = Message::Move { x: 10, y: 20 }; if let Message::Move { x, y } = msg { println!("Moving to ({}, {})", x, y); } } ``` ### if let-else ```rust fn main() { let msg = Message::Quit; if let Message::Write(text) = msg { println!("Write: {}", text); } else { println!("Not a write message"); } } ``` ### while let ```rust fn main() { let mut stack = vec![1, 2, 3]; while let Some(top) = stack.pop() { println!("{}", top); } } ``` ## Enums in Real Code ### State Machine ```rust enum State { Idle, Loading, Loaded(Vec), Error(String), } fn main() { let states = vec![ State::Idle, State::Loading, State::Loaded(vec!["item1".to_string()]), State::Error("Network error".to_string()), ]; for state in states { match state { State::Idle => println!("Idle..."), State::Loading => println!("Loading..."), State::Loaded(items) => println!("Loaded {} items", items.len()), State::Error(e) => println!("Error: {}", e), } } } ``` ## Summary - Enums define types with fixed values - Enum variants can hold data - Option represents optional values (Some/None) - Result represents success/failure (Ok/Err) - match must be exhaustive (cover all variants) - ? operator propagates errors - if let matches single pattern - while let loops while pattern matches

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →