Rust dojo第11回を開催した

第11回です。

前回はこちら。

kdnakt.hatenablog.com

 

 

[第11回の様子]

2021/09/22に第11回を開催した。

 

内容としてはRust By Example 日本語版の「3.2. 列挙型」「3.2.1. use」に取り組んだ。

 

参加者は全部で7人。今回は初ドライバのメンバーが担当。

 

Slackでの書き込みはちょっと増えた。

f:id:kidani_a:20210923012328p:plain

 

ドライバーありがとう&よろしくお願いします!

f:id:kidani_a:20210923012432p:plain

f:id:kidani_a:20210923013216p:plain

 

来週もお待ちしてます!

f:id:kidani_a:20210923013257p:plain


dojoを離れて爆走するメンバーも出てきた。すごい。

f:id:kidani_a:20210923013338p:plain

 

[学んだこと]

  • 3.2. 列挙型
  • Rustの列挙型(enum)はユニット、タプル、構造体のいずれでも定義できる
enum WebEvent {
    // ユニット
    PageLoad,
    PageUnload,
    // タプル
    KeyPress(char),
    Paste(String),
    // 構造体
    Click { x: i64, y: i64 },
}
  • JavaだとKeyPressA('A'), KeyPressB('B'), ...みたいに定義しないといけないけど、KeyPress(char)で網羅できるのは便利そう
  • enumを便利に使うにはmatchを利用する:KotlinでいうwhenJavaでいう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のenumJavaenumと比べるとはるかに柔軟に使えそうな感じ!

 

今週のプルリクエストはこちら。

github.com