第11回です。
前回はこちら。
[第11回の様子]
2021/09/22に第11回を開催した。
内容としてはRust By Example 日本語版の「3.2. 列挙型」「3.2.1. use」に取り組んだ。
参加者は全部で7人。今回は初ドライバのメンバーが担当。
Slackでの書き込みはちょっと増えた。
ドライバーありがとう&よろしくお願いします!
来週もお待ちしてます!
dojoを離れて爆走するメンバーも出てきた。すごい。
[学んだこと]
enum WebEvent { // ユニット PageLoad, PageUnload, // タプル KeyPress(char), Paste(String), // 構造体 Click { x: i64, y: i64 }, }
- Javaだと
KeyPressA('A'), KeyPressB('B'), ...
みたいに定義しないといけないけど、KeyPress(char)
で網羅できるのは便利そう - enumを便利に使うには
match
を利用する:Kotlinでいうwhen
、Javaでいうswitch
っぽいやつ
fn inspect(event: WebEvent) { match event { WebEvent::PageLoad => println!("page loaded"), WebEvent::PageUnload => println!("page unloaded"), // Destructure `c` from inside the `enum`. WebEvent::KeyPress(c) => println!("pressed '{}'.", c), WebEvent::Paste(s) => println!("pasted \"{}\".", s), // Destructure `Click` into `x` and `y`. WebEvent::Click { x, y } => { println!("clicked at x={}, y={}.", x, y); }, } }
- Kotlinの
when
同様、分岐が網羅されていないとコンパイルエラーとなる
enum WebEvent { PageLoad, PageUnload, TestEvent, } fn inspect(event: WebEvent) { match event { WebEvent::PageLoad => println!("page loaded"), WebEvent::PageUnload => println!("page unloaded"), } } // これは以下のコンパイルエラー 14 | | TestEvent, | | --------- not covered 15 | | } | |_- `WebEvent` defined here ... 20 | match event { | ^^^^^ pattern `TestEvent` not covered = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `WebEvent`
- enumの数が多いときなどには
_
を利用することで、Kotlinのelse
のように残りの分岐を全て網羅できる
#[derive(Debug)] enum WebEvent { PageLoad, PageUnload, TestEvent1, TestEvent2, TestEvent3, } fn inspect(event: WebEvent) { match event { WebEvent::PageLoad => println!("page loaded"), WebEvent::PageUnload => println!("page unloaded"), _ => println!("{:?}", event), } }
enum VeryVerboseEnumOfThingsToDoWithNumbers { Add, Subtract, } type Operations = VeryVerboseEnumOfThingsToDoWithNumbers; fn inspect(event: VeryVerboseEnumOfThingsToDoWithNumbers) { match event { VeryVerboseEnumOfThingsToDoWithNumbers::Add => println!("Add"), VeryVerboseEnumOfThingsToDoWithNumbers::Subtract => println!("Subtract"), } } fn main() { let x = Operations::Add; inspect(x); // 元の型で定義されている関数も呼び出せる }
- また、enumにはメソッドも定義することができる
enum VeryVerboseEnumOfThingsToDoWithNumbers { Add, Subtract, } impl VeryVerboseEnumOfThingsToDoWithNumbers { fn run(&self, x: i32, y: i32) -> i32 { match self { Self::Add => x + y, Self::Subtract => x - y, } } } fn main() { println!("{}", VeryVerboseEnumOfThingsToDoWithNumbers::Add.run(5,3)); // 8 }
- ライフタイムつきのstructについてもエイリアスを宣言してみる
#[derive(Debug)] struct Person<'a> { // The 'a defines a lifetime name: &'a str, age: u8, } type Person2 = Person; // 以下のコンパイルエラー 17 | type Person2 = Person; | ^^^^^^ expected named lifetime parameter | help: consider introducing a named lifetime parameter | 17 | type Person2<'a> = Person<'a>; | ^^^^ ^^^^^^^^^^
- エラーメッセージの通り、ライフタイムパラメーターも合わせて宣言すると問題なくエイリアスを宣言できた
- 3.2.1 use
- これまでは
MyEnum::MyValue1
のようにenumにアクセスしていたがこれは冗長 use
を利用することでシンプルに記述できる
enum Status { Rich, Poor, } enum Work { Civilian, Soldier, } fn main() { use crate::Status::{Poor, Rich}; // 名前指定 use crate::Work::*; // アスタリスクで全て利用可能 let _status = Poor; // Status::Poorと書かなくてもよい let _work = Civilian; // Work::Civilianと書かなくてもよい }
[まとめ]
モブプログラミングスタイルでRust dojoを開催した。
RustのenumはJavaのenumと比べるとはるかに柔軟に使えそうな感じ!
今週のプルリクエストはこちら。