Rust dojo第21回を開催した

第21回です。

前回はこちら。

kdnakt.hatenablog.com

 

 

[第21回の様子]

2021/12/08に第21回を開催した。

 

内容としてはRust By Example 日本語版の「8.5. match」、「8.5.1. デストラクト」、「8.5.1.1. タプル」、「8.5.1.2. 列挙型」、「8.5.1.3. ポインタとref」、「8.5.1.4. 構造体」に取り組んだ。

 

参加者は、ちょっと減って、6人だったけれど、どこから嗅ぎつけたのか新メンバーが参加してくれた。ありがたい🙏

 

Slackでの書き込みもいつもより活発だった。

f:id:kidani_a:20211209025832p:plain

f:id:kidani_a:20211209030025p:plain

f:id:kidani_a:20211209030127p:plain

f:id:kidani_a:20211209030258p:plain

 

次回お待ちしてます〜。

f:id:kidani_a:20211209030555p:plain

f:id:kidani_a:20211209030647p:plain

 

[学んだこと]

  • 8.5. match
  • JavaやCでいうswitchに該当するのがRustのmatch
  • 条件判定で|..=を使えるのは柔軟でよさそう
let number = 13;

match number {
    // 単一の値とのマッチをチェック
    1 => println!("One!"),
    // いくつかの値とのマッチをチェック
    2 | 3 | 5 | 7 | 11 => println!("This is a prime"),
    // 特定の範囲の値とのマッチをチェック
    13..=19 => println!("A teen"),
    // その他の場合の処理
    _ => println!("Ain't special"),
}
  • matchは式として代入もできる
let boolean = true;

// マッチは式でもある。
let binary = match boolean {
    // マッチは全ての可能な値をカバーしなくてはならない
    false => 0,
    true => 1,
}; // 最後のセミコロンが必要になる
  • matchはとりうる値の範囲を全てカバーしないとコンパイルエラーになる
let boolean = true;
let binary = match boolean {
        false => 0,
};

// 以下のコンパイルエラー
error[E0004]: non-exhaustive patterns: `true` not covered
  --> src/main.rs:24:24
   |
24 |     let binary = match boolean {
   |                        ^^^^^^^ pattern `true` 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 `bool`
let pair = (0, -2);

match pair {
    (0, y) => println!("First is `0` and `y` is `{:?}`", y), // こちらにマッチする
    (x, 0) => println!("`x` is `{:?}` and last is `0`", x),
    _      => println!("It doesn't matter what they are"),
}
enum Color {
    Red,
    Blue,
    Green,
    RGB(u32, u32, u32),
}

fn main() {
    let color = Color::RGB(122, 17, 40);
    match color {
        Color::Red   => println!("The color is Red!"),
        Color::Blue  => println!("The color is Blue!"),
        Color::Green => println!("The color is Green!"),
        Color::RGB(r, g, b) =>
            println!("Red: {}, green: {}, and blue: {}!", r, g, b),
    }
}
fn main() {
    // `i32`型へのリファレンスをアサインする。
    // `&`によってリファレンスであることを明示している。
    let reference = &4;

    match reference {
        // 上で定義した`reference`という変数が`&val`とのパターンマッチ
        // に用いられた場合、以下の2つの値が比較されていることになる。
        // `&i32`
        // `&val`
        // ^ よって`&`を落とせば、`i32`が`val`にアサインされることがわかる。
        &val => println!("Got a value via destructuring: {:?}", val),
        // ここでは値がコピーされており、println!("{:p}", &val);でポインタを見るとreferenceとは別のものになっている
    }

    // To avoid the `&`, you dereference before matching.
    // `&`を使用したくない場合は、マッチングの前にデリファレンスする。
    match *reference {
        val => println!("Got a value via dereferencing: {:?}", val),
// ここでもポインタは変わっている } }
  • &とrefは大体同じ、ということらしい
// 上記の以下の部分を
let reference = &4;

// このように書き換えても動く
let ref reference = 4;
  • 値を変更する場合
let mut mut_value = 6;

// `ref mut`を使用。
match mut_value {
    ref mut m => {
        // リファレンスを取得、値を変更するためにはデリファレンスする必要がある。
        *m += 10;
        println!("We added 10. `mut_value`: {:?}", m); // 16
    },
}

println!("{:?}", mut_value); // 参照先の値が変更されているので16が出力される
fn main() {
    struct Foo {
        x: (u32, u32),
        y: u32,
    }

    let foo = Foo { x: (1, 2), y: 3 };

    match foo {
        Foo { x: (1, b), y } => println!("First of x is 1, b = {},  y = {} ", b, y),

        // 構造体をデストラクトして変数をリネーム
        // 順番は重要ではない。
        Foo { y: 2, x: i } => println!("y is 2, i = {:?}", i),

        // 一部の変数を無視することもできる。
        Foo { y, .. } => println!("y = {}, we don't care about x", y),

        // `x`に言及していないため、以下はエラーになる。
        //Foo { y } => println!("y = {}", y),
    }
}

 

[まとめ]

モブプログラミングスタイルでRust dojoを開催した。

match式完全に理解した。でも参照は難しい...。

 

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

github.com