if let
列挙型をマッチさせるとき、場合によってはmatch
を使用すると不自然な書き方になってしまう場合があります。例えば
#![allow(unused)] fn main() { // `optional`という変数の型を`Option<i32>`に指定。 let optional = Some(7); match optional { Some(i) => println!("This is a really long string and `{:?}`", i), _ => {}, // ^ `match`は全てのパターンに対して網羅的でなくてはならないので必要。 // 冗長に見えませんか? }; }
この場合はif let
を用いたほうが美しく、失敗時の処理も柔軟に行うことができます。
fn main() { // 全て`Option<i32>`型 let number = Some(7); let letter: Option<i32> = None; let emoticon: Option<i32> = None; // `if let`文は以下と同じ意味。 // もしletがnumberをデストラクトした結果が`Some(i)`になるならば // ブロック内(`{}`)を実行します。 if let Some(i) = number { println!("Matched {:?}!", i); } // デストラクトした結果が`Some()`にならない場合の処理を明示したい場合、 // `else`を使用します。 if let Some(i) = letter { println!("Matched {:?}!", i); } else { // デストラクト失敗の場合。このブロック内を実行。 println!("Didn't match a number. Let's go with a letter!"); } // デストラクト失敗時の処理を更に分岐させることもできます。 let i_like_letters = false; if let Some(i) = emoticon { println!("Matched {:?}!", i); // デストラクト失敗。`else if`を評価し、処理をさらに分岐させます。 } else if i_like_letters { println!("Didn't match a number. Let's go with a letter!"); } else { // 今回は`else if`の評価がfalseなので、このブロック内がデフォルト。 println!("I don't like letters. Let's go with an emoticon :)!"); } }
同様にif let
は任意の列挙型のマッチに使えます。
// 列挙型の例 enum Foo { Bar, Baz, Qux(u32) } fn main() { // 変数の作成 let a = Foo::Bar; let b = Foo::Baz; let c = Foo::Qux(100); // Foo::Barにマッチする変数 if let Foo::Bar = a { println!("a is foobar"); } // 変数bはFoo::Barにマッチしないので出力されません。 if let Foo::Bar = b { println!("b is foobar"); } // 変数cはFoo::Quxにマッチしつつ値を取り出せます。 // これはSome()と同様です。 if let Foo::Qux(value) = c { println!("c is {}", value); } // 束縛も可能です。 if let Foo::Qux(value @ 100) = c { println!("c is one hundred"); } }
もう一つのメリットはif let
がパラメータを持たない列挙型にも使えることです。列挙型がPartialEq
を実装または導出していなくても問題ありません。その場合、列挙型のインスタンスは比較できないのでif Foo::Bar == a
はコンパイルエラーとなりますが、if let
は引き続き使えます。
試してみましょう。以下の例をif let
を使って直してみてください。
// この列挙型はPartialEqを実装も導出もしていません。 // そのためFoo::Bar == aはエラーとなります。 enum Foo {Bar} fn main() { let a = Foo::Bar; // Foo::Barにマッチする変数 if Foo::Bar == a { // ^-- ここでコンパイルエラー。`if let`を使ってみましょう。 println!("a is foobar"); } }