パターンマッチには複数の真マッチ条件を持つmatch
と1つの真マッチ条件を持つif let
があります。
複数の条件分岐
match
構文を使うと多くのケースに対応できます。
単純にイコールならその行の=>
より右のブロックや式が実行されます。
match 1 {
1 => println!("foo"),
2 => println!("bar"),
_ => println!("baz"),
}
// foo
ちなみに、_
行はどれにもマッチしなかった場合に実行されます
match 10 {
1 => println!("foo"),
2 => println!("bar"),
_ => println!("baz"),
}
// baz
値も返せます。
let val = match 1 {
1 => "foo",
2 => "bar",
_ => "baz",
};
assert_eq1(val, "foo");
match
では必ず条件のどれかとマッチしなければなりません。どれともマッチしない可能性が有る場合エラーとなります。
match 10 {
1 => println!("foo"),
}
// non-exhaustive patterns: `_` not covere
match
では完全なイコールだけでなく、同じ形ならマッチしてくれる点が強力です。例えばOption<T>
は値があればSome<T>
、無ければNone
となる型です。この型な値Some(33)
をmatch
に渡した時、パターンにSome(num)
と書けばそれにマッチしてくれます。そして、なんとそのnum
はlet num = 33
のように変数束縛されているので、その後の処理で使うことができます!
match Some(33) {
Some(num) => println!("Some({})", num),
None => println!("None"),
}
以下はNone
にマッチです。
match None as Option {
Some(num) => println!("Some({})", num),
None => println!("None"),
}
パターンの後にif
と条件を書くことで、さらにその条件がtrue
の時にだけ走らせられます。
let x: i32 = 33;
match Some(x) {
Some(num) if num == 33 => println!("the x equals 33"),
_ => println!("None"),
}
// "the x equals 33"
パターンは|
で区切ることで複数指定できます。
let x: i32 = 33;
let value = AB::B { value: x };
match value {
AB::A(num) | AB::B { value: num } if num == 33 => println!("the x equals 33"),
_ => println!("None"),
}
// "the x equals 33"
1つのの条件分岐
以下はSome(33)
がSome(num)
とマッチします。if let
でもマッチした時だけその後のブロック処理を走らせることができます。ちなみに、このブロックの戻り値は()
である必要があります。
if let Some(num) = Some(33) {
println!("it has walked along truthy with {}", num);
}
// it has walked along truhy with 33
もし、マッチしなかった場合の為にelse
ブロックも用意されてます。
if let Some(num) = None as Option<()> {
unreachable!();
} else {
println!("it has walked along falsy");
}
// it has walked along falsy