新しい変数バインディングを作成するために let ステートメントをよく使用しますが、let はそこで終わりではありません。実際、let ステートメントはパターン マッチング ステートメントです。これにより、内部構造に基づいて値を操作および判断したり、代数データ型から値を抽出したりすることができます。
let tuple = (1_i32, false, 3f32);
let (head, center, tail) = tuple;
上に示したように、2 番目の文を通じて、結合されたデータ構造が分解され、3 つの異なる変数に分割されます。let ステートメントでは、= 記号の左側の内容がパターン、= 記号の右側の内容が照合対象の内容になります。これは、タプル変数から 3 つの新しい変数 head、center、tail を抽出することに相当し、それぞれタプルの 3 つのメンバーに対応します。
Rust のパターン マッチング関数は、データ構造をどのように組み立て、どのように分解するかという原則に従います。次の例から錆の美しさを感じてください。
struct T1 (i32, char);
struct T2 {
item1: T1,
item2: bool,
}
fn main()
{
let x = T2 {
item1: T1(0, 'A'),
item2: false,
};
let T2 {
item1: T1(value1, value2),
item2: value3,
} = x;
println!("{} {} {}", value1, value2, value3);
}
Rustの「パターンマッチング」関数はlet、match、if let、while let、関数呼び出し、クロージャ呼び出しなどに登場します。
マッチ
match パターン マッチングはプロセス制御に使用され、現在の値が一連のパターンの 1 つと一致するかどうかを確認します。パターンは、リテラル、変数、ワイルドカード、およびその他のコンテンツで構成できます。各パターンは分岐であり、プログラムは一致するパターンに従って対応するコードを実行します。
Rust では、一致パターンのマッチングが網羅的であること、つまりすべての可能性を網羅する必要があります。そうしないと、プログラム エラーが発生します。これを行う 1 つの方法は、ワイルドカード "_" を他の分岐の後に配置することです。ワイルドカード "_" は、上記で指定されていないすべての可能なパターンに一致します。
- 垂直バー (|) を使用して、一致分岐内で複数のパターンを組み合わせることができます。
- 範囲内の値を一致させるには... を使用します。
- 演算子 @ を使用して、パターン内の値を分岐の右側のコードで使用する変数にバインドします。このタイプの一致はバインド パターンと呼ばれます。一致分岐に保護を追加するには、if キーワードを使用します。
- if を「マッチガード」として使用できます。一致が成功し、if 条件が満たされると、次のステートメントが実行されます。
- ワイルドカード「_」は、上記で指定されていないすべての可能なパターンに一致します。
fn main() {
let age = 6;
match age {
0 => println!("You are a baby."),
1..=7 => println!("You are a toddler."),
8|9|10|11 => println!("You are a schoolchild."),
i if i >= 12 && i<=17 => println!("You are a teenager."),
n @ 18 => println!("You are {}.",n),
19..=100 => println!("You are an adult."),
_ => println!("Cool !"),
}
}
if let&while let
if let および while let 式は、コードを簡素化するために、一部のシナリオで一致パターン マッチングを置き換えることができます。
match と比較すると、 let は関心のある値のみを照合することができ、 else は残りのケースの処理を続行するために使用できます。
fn main() {
let value = Some(7);
if let Some(7) = value {
println!("seven"); }
if let Some(v) = value {
println!("Some({})",v);
}else{
println!("None");
}
}
条件付きループ while let は、失敗が発生するまで同じパターン マッチを繰り返し実行します。
fn while_let_vec() {
let mut vec = vec![1, 2, 3, 4, 5];
while let Some(value) = vec.pop() {
println!("{}", value);
}
}
関数パラメータ (クロージャ)
上記の 2 つの状況を通して、すでに大まかな理解はできたと思いますが、例を見てみましょう。
struct T {
item1: char,
item2: bool,
}
fn test( T{item1: arg1, item2: arg2} : T) {
println!("{} {}", arg1, arg2);
}
fn main()
{
let x = T {
item1: 'A',
item2: false,
};
test(x);
}
関数パラメータ リストと同様に、クロージャ パラメータ リストでもパターンを使用できます。
その他(させる、させる)
遭遇する可能性のあるシナリオもいくつかありますが、パターン マッチングのルールをすでに理解していれば、関連するコードを見たり書いたりしても、おそらくすぐに実行できるでしょう。
記事の冒頭でも紹介していますが、それが自然かどうかは例題を見ていただければと思います。
let v = vec!['a', 'b', 'c'];
for (index, value) in v.iter().enumerate() {
println!("{} is at index {}", value, index);
}