パターンは値の形を記述し、その部分に変数を束縛します。パターンは Rust のものですが、形の種類が少なくなっています。パターンが現れる場所:
| 場所 | 反駁不能である必要 |
|---|---|
let pat = value; | あり |
| 関数とクロージャの引数 | あり |
for pat in iterable | あり |
match のアーム | なし |
if let pat = value、while let pat = value | なし |
パターンの形
| パターン | 例 | 一致するもの |
|---|---|---|
| ワイルドカード | _ | 何にでも一致し、何も束縛しません |
| 束縛 | x、mut x | 何にでも一致し、それを x に束縛します |
| リテラル | 0、-1、true、"Mio"、0.5 | リテラルと等しい値 |
| 範囲 | 3..=5、0..10、6..、..=2 | 範囲内の整数 |
| パス | Route::None、ORIGIN、Self::EMPTY | ユニットバリアント、ユニット構造体、定数 |
| タプル | (a, _, true)、(first, ..) | タプルを要素ごとに |
| タプル構造体 / バリアント | Some(x)、EntityId(id)、Pair(a, ..) | タプル構造体またはタプルバリアントをフィールドごとに |
| 構造体 / 構造体バリアント | Point { x, y: 0 }、Shape::Rect { w, .. } | 構造体または構造体形式のバリアントをフィールド名で |
| 代替 | Map::A | Map::B、| 1 | 2 | いずれかの代替に一致するもの |
| 括弧 | (Some(_) | None) | 内側のパターン |
スライスや配列のパターン([a, b])、参照パターン(&x)、ref や ref mut の束縛、name @ pattern の束縛はありません。
束縛
識別子パターンは新しい変数を束縛します。ただし、その名前がスコープ内のユニット構造体、ユニットバリアント、定数に解決される場合は、その値と比較するパスパターンになります。これは Rust と同じです。
const LIMIT: u32 = 3;
const fn at_limit(n: u32) -> bool { match n { LIMIT => true, // the constant `LIMIT`, not a new binding _ => false, }}mut x は束縛を可変にします。1 つのパターンで同じ名前を 2 回束縛すると E1024 です。代替パターン A | B では、すべての代替が同じ名前を束縛しなければなりません(E1025)。static はパターンに使えません(E2035)。
&T や &mut T 型の値を束縛以外のパターンと照合すると、参照を通り抜けて照合し、内側の束縛は部分への参照(&T または &mut T)を束縛します。Rust のデフォルト束縛モードと同じです。
リテラルパターン
整数リテラルは照合する型に収まらなければならず(E2013)、負の値も書けます。文字列リテラルは Text に、小数リテラルは Decimal に、true と false は bool に一致します。照合する値と異なる型のリテラルは E2001 です。
範囲パターン
match AFFECTION_MIO { 0 => MioIgnores(), 1..=2 => MioShrugs(), 3.. => MioSmiles(),}| 形 | 一致するもの |
|---|---|
a..=b | a から b まで(両端を含む) |
a..b | a から b まで(b を含まない) |
a.. | a 以上 |
..=b | b 以下 |
端は整数リテラル(負も可)か、整数定数へのパスです。範囲パターンは整数(Rust 整数と Int<lo, hi>)にだけ一致し、それ以外の型に使うと E2001 です。..b というパターンはありません。.. 単独は下記の残余パターンです。
残余パターン
タプル、タプル構造体、構造体のパターンの中の .. は、書かれていないすべてのフィールドを表します: (first, ..)、Pair(a, ..)、Shape::Rect { w, .. }。タプルやタプル構造体のパターンでは 1 回だけ、任意の位置に書けます。(.., last) は最後の要素に一致します。構造体パターンでは最後に書きます。
構造体パターン
Point { x, y: 0 } は y が 0 の Point に一致し、x を束縛します。単独で書いたフィールド(x、mut x)は同名の変数を束縛し、field: pattern はフィールドをパターンと照合します。書かれていないフィールドは何にでも一致します。Rust と異なり末尾の .. は省略できますが、省略を明示するために書くこともできます。未知のフィールドは E2020 です。形の合わないパターン(構造体バリアントにタプルパターンを使う、タプルパターンのフィールド数が違う、バリアントの代わりに enum 名を書く)は E2035 です。
match と網羅性
match (VISITED_A, VISITED_B) { (true, true) => FestivalEnd(), (true, false) | (false, true) => s!(t!["One more stall."]), (false, false) => {}}match のアームは pattern => expression で、ガードを付けて pattern if condition => expression とも書けます。アームは順に試され、パターンが一致しガードが真である最初のアームが実行されます。アームはカンマで区切りますが、本体がブロックのアームの後ではカンマを省略できます。
match は網羅的でなければなりません。検査対象の型のすべての値が、いずれかのアームに一致する必要があります(E2037)。メッセージにはどのアームにも一致しない値が示されます。前のアームですでに網羅されていて決して実行されないアームは警告です(W2039)。
コンパイラーが値を把握している型:
| 型 | 検査が把握する値 |
|---|---|
bool | true、false |
Int<lo, hi> | ちょうど lo から hi まで。Int<0, 2> は _ なしで 0、1、2 によって網羅されます |
| Rust 整数 | 型の全範囲。u8 の match には 255 までのアームか _ が必要です |
| enum | バリアント。フィールドの中まで再帰的に |
| 構造体、タプル、配列 | 1 つの形。フィールドの中まで再帰的に |
&T、&mut T | T の値 |
Text、String、Decimal、Rat、ジェネリクスパラメーター、その他のビルトイン型 | 無制限。リテラルはそれ自身しか網羅しないので、_ か束縛のアームが必要です |
ガードは考慮されません。ガード付きのアームは検査上何も網羅しません。パターンとして使った定数は、初期化子がリテラル、コンストラクター、またはそれらのタプルや構造体であれば、その値を網羅します。そうでなければその定数自身だけを網羅します。
choice!{…} の選択肢は普通の enum 値なので、それに対する match も他と同じく検査されます。選択肢にアームがないバリアントも、処理するか _ で網羅しなければなりません。
反駁可能性
型のすべての値に一致するパターンを反駁不能といいます。let、for、引数のパターンは反駁不能でなければなりません(E2038)。
let (a, b) = pair; // irrefutablelet Point { x, .. } = p; // irrefutablelet Some(v) = maybe; // E2038: `None` is not covered反駁可能なパターンには if let か match を使います。
if let Some(v) = maybe { use_value(v);}let … else はなく、if let を && で他の条件と組み合わせることもできません。