[Rust] 「パターン」を用いた非構造化変数束縛

Rust で「パターン」について調べるとき `match` 式に注目しがちかもしれませんが、関数等の引数や `let` 宣言等、変数束縛 (代入のようなもの) をするような場所でも使えます。
他プログラミング言語における「分割代入」にあたる変数束縛もできます。

本記事では Rust の「パターン」の中でも「非構造化」についてまとめます。

※本記事では "destructuring" を「非構造化」と訳していますが、Rust の日本語版ドキュメントでは「分解」や「分配」と訳されています。

# 1. 「パターン」の概要

「パターン」は以下の箇所で利用できます。

- `let` 宣言
- 関数またはクロージャの引数
- `match` 式
- `if let` 式
- `while let` 式
- `for` 式

「パターン」の役割は以下の 2 つです。

1. 「値の構造が目的の構造と一致するか」を調べたいとき、その「目的の構造」を表現する
1. 「値の構造が目的の構造と一致した」とき、その「構造」に基づいて値を非構造化し、変数を非構造化した値に束縛する (オプションな役割)

参考「[Patterns - The Rust Reference](https://doc.rust-lang.org/reference/patterns.html)」
参考「[Pattern Syntax - The Rust Programming Language](https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html)」

# 2. 非構造化変数束縛

変数を束縛することから最終的に「識別子パターン」として解析されることになりますが、そこまで解析される過程等をまとめます。

(「ワイルドカードパターン」や「残余パターン」で変数束縛されないこともあります。)

参考「[Identifier patterns - Patterns - The Rust Reference](https://doc.rust-lang.org/reference/patterns.html#identifier-patterns)」

## 2.1. 「参照パターン」による参照外し

「参照パターン」によって参照外しをすることができます。

```rust:let&nbsp;宣言での例
let foo = 23;

let bar = &foo; // 借用 (変数 bar は参照型)

let baz = *bar; // 参照外し演算子 * による参照外し

let &qux = bar; // 参照パターンによる参照外し
```

```rust:クロージャの引数での例
let something = |&foo| { // 参照パターンによる参照外し
    let bar = String::from(foo);
    println!("{}", bar);
};

let baz = "Baz";

let qux = &baz;

something(qux);
```

参考「[Reference patterns - Patterns - The Rust Reference](https://doc.rust-lang.org/reference/patterns.html#reference-patterns)」

## 2.2. 「スライスパターン」による分割代入

```rust
let something = [10, 20, 30]; // Vec も可

let [foo, bar, baz] = something; // 配列の分割
println!("{} {} {}", foo, bar, baz);

let [foo, bar, _] = something; // 配列の分割: ワイルドカードパターン
println!("{} {}", foo, bar);

let [foo, ..] = something; // 配列の分割: 残余パターン
println!("{}", foo);

let [foo, bar @ ..] = something; // 配列の分割: 識別子パターン: @ サブパターン: 残余パターン
println!("{} {:?}", foo, bar);

let [foo, bar, ref baz] = something; // 配列の分割: 識別子パターン: 借用
println!("{} {} {}", foo, bar, *baz);
```

※非構造化では、分解した変数ごとに右辺側に借用演算子 (参照演算子) `&` を付けて借用することができないため、借用したい場合は左辺側の識別子 (変数名) 前にキーワード `ref` を付けて借用します。
※キーワード `mut` もキーワード `ref` と同様に左辺側の識別子 (変数名) 前で利用できます。

参考「[Slice patterns - Patterns - The Rust Reference](https://doc.rust-lang.org/reference/patterns.html#slice-patterns)」

## 2.3. 「タプルパターン」によるタプルの分解

```rust
let something = (23, 'B', true);

let (foo, bar, baz) = something; // タプルの分解
println!("{} {} {}", foo, bar, baz);

let (foo, bar, _) = something; // タプルの分解: ワイルドカードパターン
println!("{} {}", foo, bar);

let (foo, ..) = something; // タプルの分解: 残余パターン
println!("{}", foo);

// スライスパターン以外では不可
// let (foo, bar @ ..) = something; // タプルの分解: 識別子パターン: @ サブパターン: 残余パターン

let (foo, bar, ref baz) = something; // タプルの分解: 識別子パターン: 借用
println!("{} {} {}", foo, bar, *baz);
```

※キーワード `ref` や `mut` は「スライスパターン」と同様。

参考「[Tuple patterns - Patterns - The Rust Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-patterns)」

## 2.4. 「構造体パターン」による構造体の分解

```rust
struct Something {
    foo: i32,
    bar: char,
    baz: bool,
}

//
let something = Something {
    foo: 23,
    bar: 'B',
    baz: true,
};

let Something { foo, bar, baz } = something; // 構造体の分解
println!("{} {} {}", foo, bar, baz);

let Something { foo, bar, baz: qux } = something; // 構造体の分解: 識別子パターン (別名): qux = baz
println!("{} {} {}", foo, bar, qux);

let Something { foo, bar, baz: _ } = something; // 構造体の分解: ワイルドカードパターン: _ = baz
println!("{} {}", foo, bar);

let Something { foo, .. } = something; // 構造体の分解: 残余パターン
println!("{}", foo);

let Something { foo, bar, ref baz } = something; // 構造体の分解: 借用: ref baz = baz
println!("{} {} {}", foo, bar, *baz);
```

※キーワード `ref` や `mut` は「スライスパターン」と同様。
※厳密には、構造体の場合、キーワード `ref` や `mut` は「構造体パターンフィールド」として解析される場合と「識別子パターン」として解析される場合があります。

参考「[Struct patterns - Patterns - The Rust Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)」

## 2.5. 「タプル構造体パターン」によるタプル構造体の分解

「タプル構造体パターン」では「構造体パターン」と同様に構造体のパスの一致が確認され、「タプルパターン」と同様に要素が分解されます。

```rust
struct Something(i32, char, bool);

//
let something = Something(23, 'B', true);

let Something(foo, bar, baz) = something; // タプル構造体の分解
println!("{} {} {}", foo, bar, baz);

let Something(foo, bar, _) = something; // タプル構造体の分解: ワイルドカードパターン
println!("{} {}", foo, bar);

let Something(foo, ..) = something; // タプル構造体の分解: 残余パターン
println!("{}", foo);

// スライスパターン以外では不可
// let Something (foo, bar @ ..) = something; // タプル構造体の分解: 識別子パターン: @ サブパターン: 残余パターン

let Something(foo, bar, ref baz) = something; // タプル構造体の分解: 識別子パターン: 借用
println!("{} {} {}", foo, bar, *baz);
```

※キーワード `ref` や `mut` は「スライスパターン」と同様。

参考「[Tuple struct patterns - Patterns - The Rust Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-struct-patterns)」

## 2.6. 列挙型の列挙子の分解

列挙型は列挙子の構造ごとに「パスパターン」や「タプル構造体パターン」、「構造体パターン」として解析され、分解されます。

(※「パスパターン」は変数を束縛しません。)

列挙型 `Option` や `Result` で使うことが多いかと思います。

```rust:Option&nbsp;型での例
let foo = Some(23);

if let Some(bar) = foo { // 列挙子の分解: タプル構造体パターン
    println!("{}", bar);
}
```

```rust:Result&nbsp;型での例
let foo: Result<(), _> = Err("Error");

if let Err(bar) = foo { // 列挙子の分解: タプル構造体パターン
    eprintln!("{}", bar);
    // process::exit(1);
}
```

参考「[Destructuring - Patterns - The Rust Reference](https://doc.rust-lang.org/reference/patterns.html#destructuring)」
参考「[Tuple struct patterns - Patterns - The Rust Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-struct-patterns)」
参考「[Path patterns - Patterns - The Rust Reference](https://doc.rust-lang.org/reference/patterns.html#path-patterns)」