<style> /* basic design */ .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6, .reveal section, .reveal table, .reveal li, .reveal blockquote, .reveal th, .reveal td, .reveal p { font-family: 'Meiryo UI', 'Source Sans Pro', Helvetica, sans-serif, 'Helvetica Neue', 'Helvetica', 'Arial', 'Hiragino Sans', 'ヒラギノ角ゴシック', YuGothic, 'Yu Gothic'; text-align: left; line-height: 1.5; letter-spacing: normal; text-shadow: none; word-wrap: break-word; color: #AAA; } .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {font-weight: bold;} .reveal h1, .reveal h2, .reveal h3 {color: #2980b9;} .reveal th {background: #DDD;} .reveal section img {background:none; border:none; box-shadow:none; max-width: 95%; max-height: 95%;} .reveal blockquote {width: 90%; padding: 0.5vw 3.0vw;} .reveal table {margin: 1.0vw auto;} .reveal code {line-height: 1.2;} .reveal p, .reveal li {padding: 0vw; margin: 0vw;} .reveal .box {margin: -0.5vw 1.5vw 2.0vw -1.5vw; padding: 0.5vw 1.5vw 0.5vw 1.5vw; background: #EEE; border-radius: 1.5vw;} /* table design */ .reveal table {background: #f5f5f5;} .reveal th {background: #444; color: #fff;} .reveal td {position: relative; transition: all 300ms;} .reveal tbody:hover td { color: transparent; text-shadow: 0 0 3px #AAA;} .reveal tbody:hover tr:hover td {color: #444; text-shadow: 0 1px 0 #CCC;} /* blockquote design */ .reveal blockquote { width: 90%; padding: 0.5vw 0 0.5vw 6.0vw; font-style: italic; background: #f5f5f5; } .reveal blockquote:before{ position: absolute; top: 0.1vw; left: 1vw; content: "\f10d"; font-family: FontAwesome; color: #2980b9; font-size: 3.0vw; } /* font size */ .reveal h1 {font-size: 4.0vw;} .reveal h2 {font-size: 3.5vw;} .reveal h3 {font-size: 2.8vw;} .reveal h4 {font-size: 2.6vw;} .reveal h5 {font-size: 2.4vw;} .reveal h6 {font-size: 2.2vw;} .reveal section, .reveal table, .reveal li, .reveal blockquote, .reveal th, .reveal td, .reveal p {font-size: 2.0vw;} .reveal code {font-size: 1.0vw;} /* new color */ .red {color: #EE6557;} .blue {color: #16A6B6;} /* split slide */ #right {left: -18.33%; text-align: left; float: left; width: 50%; z-index: -10;} #left {left: 31.25%; text-align: left; float: left; width: 50%; z-index: -10;} </style> <style> /* specific design */ .reveal h2 { padding: 0 1.5vw; margin: 0.0vw 0 2.0vw -2.0vw; border-left: solid 1.0vw #2980b9; border-bottom: solid 0.6vw #d7d7d7; } </style> <!-- --------------------------------------------------------------------------------------- --> # Rust Study Session \#4 ## Ch. 6: Enums and Pattern Matching ### 2020.08.28 - Salvatore La Bua --- ## Summary - Defining an __*enum*__ - Encoding meaning into the data. - The __*match*__ control flow operator - Different behaviour for each value. - Concise control flow with __*if let*__ - An alternative match syntax. --- ## Defining an Enum ### What are enums - Enumerations allow the definition of custom types by enumerating all the possible *variants*. - In some ways, enums are similar to structs. --- ### Custom data type: IP version #### Enum definition ```rust= enum IpAddrKind { V4, V6, } ``` #### Instances ```rust= let four = IpAddrKind::V4; // type::variant let six = IpAddrKind::V6; ``` --- ### Custom data type: IP version #### Function definition ```rust= fn route(ip_kind: IpAddrKind) {} ``` #### Function call ```rust= route(IpAddrKind::V4); route(IpAddrKind::V6); ``` --- ### Custom data type: IP version #### Implementation using structs ```rust= 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"), }; ``` --- ### Custom data type: IP version #### Implementation using enums ```rust= enum IpAddr { V4(String), V6(String), } let home = IpAddr::V4(String::from("127.0.0.1")); let loopback = IpAddr::V6(String::from("::1")); ``` Similarly, ```rust= enum IpAddr { V4(u8, u8, u8, u8), V6(String), } let home = IpAddr::V4(127, 0, 0, 1); let loopback = IpAddr::V6(String::from("::1")); ``` --- ### Rust built-in IpAddr type implementation ```rust= struct Ipv4Addr { // --snip-- } struct Ipv6Addr { // --snip-- } enum IpAddr { V4(Ipv4Addr), V6(Ipv6Addr), } ``` ※ Built-in [IpAddr documentation](https://doc.rust-lang.org/std/net/enum.IpAddr.html) --- ### Custom data type: Message #### Definition ```rust= enum Message { Quit, Move { x: i32, y: i32 }, // <- anonymous struct Write(String), ChangeColor(i32, i32, i32), } ``` Similarly, ```rust= struct QuitMessage; // unit struct struct MoveMessage { x: i32, y: i32, } struct WriteMessage(String); // tuple struct struct ChangeColorMessage(i32, i32, i32); // tuple struct ``` --- ### Custom data type: Message #### Defining methods ```rust= impl Message { fn call(&self) { // method body would be defined here } } let m = Message::Write(String::from("hello")); m.call(); ``` --- ### The Option enum - Sometimes it is necessary to specify that a data type may or may not contain a value. - The __Null__ value, which is commonly available in other programming languages, is purposedly missing in Rust. - The __Option__ enum replaces the use of Null in Rust. --- ### The Option enum #### Built-in definition ```rust= enum Option<T> { Some(T), None, } ``` ※ [Option documentation](https://doc.rust-lang.org/std/option/enum.Option.html) - Automatically included in the prelude. - The Option:: namespace is not needed. --- ### The Option enum #### Instances ```rust= let some_number = Some(5); let some_string = Some("a string"); let absent_number: Option<i32> = None; ``` #### Variants - Some - Data type is automatically inferred. - None - It is necessary to specify the data type. --- ### The Option enum #### An example ```rust= let x: i8 = 5; let y: Option<i8> = Some(5); let sum = x + y; ``` ※ This code does not compile - Option\<i8\> and i8 are not of the same type. --- ## The *match* operator ### Coins example ```rust= 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, } } ``` --- ### Coins example #### A different implementation ```rust= fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => { println!("Lucky penny!"); 1 } Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } } ``` --- ### Coins example #### Pattern-to-value binding ```rust= #[derive(Debug)] // required to be able to print the enum enum UsState { Alabama, Alaska, // --snip-- } enum Coin { Penny, Nickel, Dime, Quarter(UsState), } ``` --- ### Coins example #### Pattern-to-value binding ```rust= 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 } } } ``` --- ### Matching with Option\<T\> #### Matching and binding ```rust= fn plus_one(x: Option<i32>) -> Option<i32> { match x { None => None, Some(i) => Some(i + 1), } } let five = Some(5); let six = plus_one(five); let none = plus_one(None); ``` --- ### Matches are exhaustive ```rust= fn plus_one(x: Option<i32>) -> Option<i32> { match x { Some(i) => Some(i + 1), } } ``` ※ This code does not compile - The None branch is missing. --- ### The _ placeholder ```rust= let some_u8_value = 0u8; match some_u8_value { 1 => println!("one"), 3 => println!("three"), 5 => println!("five"), 7 => println!("seven"), _ => (), } ``` --- ## Concise Control Flow with *if let* ### Match example ```rust= let some_u8_value = Some(0u8); match some_u8_value { Some(3) => println!("three"), _ => (), } ``` Or using __if let__, ```rust= if let Some(3) = some_u8_value { println!("three"); } ``` ※ Cleaner code, but exhaustive check no longer enforced --- ### Coins example ```rust= let mut count = 0; match coin { Coin::Quarter(state) => println!("State quarter from {:?}!", state), _ => count += 1, } ``` Or using __if let__, ```rust= let mut count = 0; if let Coin::Quarter(state) = coin { println!("State quarter from {:?}!", state); } else { count += 1; } ``` <div style="text-align: right">□</div> --- ## References From __The Rust Programming Language__ book: - Ch. 06: Enums and Pattern Matching [[EN]](https://doc.rust-lang.org/book/ch06-00-enums.html) [[JP]](https://doc.rust-jp.rs/book-ja/ch06-00-enums.html) - Ch. 18: Patterns and Matching [[EN]](https://doc.rust-lang.org/book/ch18-00-patterns.html) [[JP]](https://doc.rust-jp.rs/book-ja/ch18-00-patterns.html) Appendices: - IpAddr documentation: [[EN]](https://doc.rust-lang.org/std/net/enum.IpAddr.html) - Option documentation: [[EN]](https://doc.rust-lang.org/std/option/enum.Option.html) ---
{"metaMigratedAt":"2023-06-15T12:02:48.588Z","metaMigratedFrom":"YAML","title":"Rust Ch.6 - Enums and Pattern Matching","breaks":false,"description":"Rust Ch.6 - Enums and Pattern Matching","slideOptions":"{\"theme\":\"black\",\"slideNumber\":\"c/t\",\"center\":false,\"transition\":\"fade\",\"keyboard\":true}","contributors":"[{\"id\":\"c5f0d40d-be35-4660-a8b4-7736feeb9327\",\"add\":11202,\"del\":1654}]"}
    1033 views