第21回です。
前回はこちら。
[第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での書き込みもいつもより活発だった。
次回お待ちしてます〜。
[学んだこと]
- 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`
- 8.5.1. デストラクト
- matchでは値をデストラクトして取り出すことができる
- 8.5.1.1. タプル
- タプルから値を取り出す場合
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"), }
- 8.5.1.2. 列挙型
- 列挙型でも同様
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), } }
- 8.5.1.3. ポインタとref
- ポインタをデリファレンスする場合には
*
を用いる - デストラクトには
&
、ref
、ref mut を利用する
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が出力される
- 8.5.1.4. 構造体
- 構造体の場合はフィールド名を指定してデストラクトする
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式完全に理解した。でも参照は難しい...。
今週のプルリクエストはこちら。