#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演算子]]