<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}]"}