#TheBook #Rust https://doc.rust-jp.rs/book-ja/ch18-00-patterns.html ## パターンが使用されることのある箇所全部 - `while let`ループ ## 論駁可能性: パターンが合致しないかどうか - [[論駁可能]]と[[論駁不可能]] ## パターン記法 - [[シャドーイング]] - `参照の分配`が英語版ではない - [[Rust 2018]]以降でエラーにならなくなったから? - `_`で関数の引数が使われていないことを示す - 通常はシグニチャから削除すべき - だが[[トレイト]]の実装などで便利なことがある `_を引数に使う例` ```rust trait Adder { fn add(x: i32, y: i32) -> i32; } struct Right {} impl Adder for Right { fn add(x: i32, y: i32) -> i32 { x + y } } struct Wrong {} impl Adder for Wrong { fn add(x: i32, _: i32) -> i32 { x + x } } fn main() { assert_eq!(3, Right::add(1, 2)); assert_eq!(2, Wrong::add(1, 2)); } ``` - [[Rustで変数名がアンダースコア(_)だと値を束縛しない]] - `..`は残りのパターンを無視する - 末尾以外でも使える `末尾以外で..を使う` ```rust fn main() { let tp = (1, 2, 3, 4, 5); let (first, .., last) = tp; eprintln!("first = {:?}", first); // 1 eprintln!("last = {:?}", last); // 5 } ``` [[パターンマッチ (Rust)|パターンマッチ]]で導入された変数は値に束縛される。 ```rust fn main() { let s = Some(String::from("hoge")); if let Some(x) = s { // x: String println!("{x}") } // Use of partially moved value: `s` println!("{}", s.unwrap()); } ``` 上記ケースでは以下のようにすれば解決できる。 ```rust fn main() { let s = Some(String::from("hoge")); if let Some(x) = &s { println!("{x}") } println!("{}", s.unwrap()); } ``` [[パターンマッチ (Rust)|パターンマッチ]]の場合、以下でも解決できそうに見える。 ```rust fn main() { let robot_name = Some(String::from("mimizou")); match &robot_name { Some(name) if name == "mimizou" => println!("pigi----!"), Some(name) => println!("Found a name: {}", name), None => (), } // Borrow of partially moved value: `robot_name` println!("robot_name is: {:?}", robot_name); } ``` なのに `ref` を使ってこうすることの意味や? 先ほどのケースだとマッチしないケースがあると思うのだが、文字列に関しては事象を再現できなかった。。 ```rust fn main() { let robot_name = Some(String::from("mimizou")); match robot_name { Some(ref name) if name == "mimizou" => println!("pigi----!"), Some(ref name) => println!("Found a name: {}", name), None => (), } // Borrow of partially moved value: `robot_name` println!("robot_name is: {:?}", robot_name); } ``` [[マッチガード]]の利用について、[[アーム]]で変数を使う場合、そのままだと[[シャドーイング]]されて新しい変数と見なされてしまうから、[[マッチガード]]を使えってことか。 ```rust fn main() { let n = 1; // Unused variable: 'max' let max = 100; match n { // Variable `max` is never used. max => println!("max!"), // Unreachable pattern. _ => println!("not max..."), }; } ``` 期待値は`not max...`だけど`max!`が表示される。これを ```rust fn main() { let n = 1; let max = 100; match n { x if x == max => println!("max!"), _ => println!("not max..."), }; } ``` とすればOK。 - [[at演算子]]