100日後にRustをちょっと知ってる人になる: [Day 65]let-else と if-else
Day 65 のテーマ
Day 64 で Rust 1.65.0 のアナウンスノートを眺めてみましたが、そこに let-else
文に関する内容がありました。それについては、昨日どのような構文になるかは少し記載したのですが、元々 今までのバージョンにあった let
式の使い方との比較などは説明をしていませんでした。
つまり、今回のバージョンアップで、let-else
文が追加されることによって、今まで出来ていなかったどのような事が解決できるようになったのか、眺めてみたいかなと思います。
既存の if-let
Rust 公式ドキュメント (https://doc.rust-lang.org/) の中では if let
文について、列挙型とパターンマッチングのセクションで紹介されています。
if let
を使用しないで match
によるパターンマッチングをしているケースをまず見てみます。
let optional = Some(5);
match optional {
Some(i) => {
println!("Matched {:?}!", i)
},
_ => {},
}
上記の例ではまず、Option
の列挙子でタプル構造体な Some(T)
に数値を入れています。それを match
でマッチングさせて取り出しています。
マッチングしている対象の値が1つしかありません。match
はマッチングする条件を記述するためのものなので、当然ながら複数の条件を定義できます。
今回のように対象の値を1つしか定義しないパターンマッチングならば、if let
という記法の方がシンプルに記述できます。
ちなみに、この if let
ですが、if
let
ではないことに注意してください。if
と let
を組み合わせて利用しているように一見見えてしまいますが、この if let
は1つのキーワードとして定義されているものです。
そして、以下のように書き直せます。
if let Some(i) = optional {
println!("Matched {:?}!", i);
}
ここの意味は let Some(i) = optional
が、真なのか偽なのかを判定しています。
この let
は代入という意味よりはパターンマッチングとして使われています。
// EXPRESSION: 何らかの値を返す「式」のこと
// PATTERN: 値がマッチするか否かに用いられる「パターン」のこと
let PATTERN = EXPRESSION;
もちろんパターンにマッチしない場合のケースとして、else
を使用可能です。else
の後のブロックで束縛を行います。
if let Some(i) = optional {
println!("マッチしました {:?}!", i);
} else {
rintln!{"マッチしません {:?}!", i};
}
match
で記述するよりも随分とシンプルになりますよね。
let-else
新しく導入された let-else
は次のような構文でした。
let パターン = 値 else { never型を返す処理 };
つまり、if-let
とはパターンに対してマッチする場合の変数を束縛することは共通しています。
異なっているのは、どこで束縛しているかという点です。
-
if-let: 阿多田らしく作ったブロック内で変数を束縛
- 真の時と偽の時の処理は対等
-
let-else: 現在のブロックで変数を束縛
- 真の時のが想定処理で
else
は異常系という意味が強い
- 真の時のが想定処理で
実施する内容は似てはいるのですが、書き方の意味合いや束縛した変数の使いまわしなどによって、if-else
か let-else
かの選択肢の幅が増えそうなのかと思いました。
Day 65 のまとめ
もともと if-else
を使っていた人たちにとっては、1.65.0 で新しく安定化した let-else
は便利な構文と感じられているのではないかなと思いました。
Rust は条件やマッチングに関する記述の仕方が豊富だと改めて感じるリリース内容でした。
Discussion