論駁可能性: パターンが合致しないかどうか

パターンには2つの形態があります: 論駁可能なものと論駁不可能なものです。渡される可能性のあるあらゆる値に合致するパターンは、 論駁不可能なものです。文let x = 5;xは一例でしょう。xは何にでも合致し、故に合致に失敗することがあり得ないからです。 なんらかの可能性のある値に対して合致しないことがあるパターンは、論駁可能なものです。 一例は、式if let Some(x) = a_valueSome(x)になるでしょう; a_value変数の値がSomeではなく、 Noneなら、Some(x)パターンは合致しないでしょうから。

関数の引数、let文、forループは、値が合致しなかったら何も意味のあることをプログラムが実行できないので、 論駁不可能なパターンしか受け付けられません。if letwhile let式は、定義により失敗する可能性を処理することを意図したものなので、 論駁可能なパターンのみを受け付けます: 条件式の機能は、成功か失敗によって異なる振る舞いをする能力にあるのです。

一般的に、論駁可能と論駁不可能なパターンの差異について心配しなくてもいいはずです; しかしながら、 エラーメッセージで見かけた際に対応できるように、論駁可能性の概念に確かに慣れておく必要があります。 そのような場合には、コードの意図した振る舞いに応じて、パターンかパターンを使用している構文を変える必要があるでしょう。

コンパイラが論駁不可能なパターンを必要とする箇所で論駁可能なパターンを使用しようとしたら、何が起きるかとその逆の例を見ましょう。 リスト18-8はlet文を示していますが、パターンにはSome(x)と指定し、論駁可能なパターンです。 ご想像通りかもしれませんが、このコードはコンパイルできません。

let Some(x) = some_option_value;

リスト18-8: letで論駁可能なパターンを使用しようとする

some_option_valueNone値だったなら、パターンSome(x)に合致しないことになり、パターンが論駁可能であることを意味します。 ですが、let文は論駁不可能なパターンしか受け付けられません。None値に対してコードができる合法なことは何もないからです。 コンパイル時にコンパイラは、論駁不可能なパターンが必要な箇所に論駁可能なパターンを使用しようとしたと文句を言うでしょう:

error[E0005]: refutable pattern in local binding: `None` not covered
(エラー: ローカル束縛に論駁可能なパターン: `None`がカバーされていません)
 -->
  |
3 | let Some(x) = some_option_value;
  |     ^^^^^^^ pattern `None` not covered

パターンSome(x)で全ての合法な値をカバーしなかった(できませんでした!)ので、 コンパイラは当然、コンパイルエラーを生成します。

論駁不可能なパターンが必要な箇所に論駁可能なパターンがある問題を修正するには、パターンを使用するコードを変えればいいのです: letの代わりにif letを使用できます。そして、パターンが合致しなかったら、コードは合法に継続する手段を残して、 波括弧内のコードを飛ばすだけでしょう。リスト18-9は、リスト18-8のコードの修正方法を示しています。


#![allow(unused)]
fn main() {
let some_option_value: Option<i32> = None;
if let Some(x) = some_option_value {
    println!("{}", x);
}
}

リスト18-9: letではなく、if letと論駁可能なパターンを含むブロックを使用する

コードに逃げ道を与えました!このコードは完全に合法ですが、エラーを受け取らないで論駁不可能なパターンを使用することはできないことを意味します。 リスト18-10のように、xのような常にマッチするパターンをif letに与えたら、コンパイルできないでしょう。

if let x = 5 {
    println!("{}", x);
};

リスト18-10: if letで論駁不可能なパターンを使用してみる

コンパイラは、論駁不可能なパターンとif letを使用するなんて道理が通らないと文句を言います:

error[E0162]: irrefutable if-let pattern
(エラー: 論駁不可能なif-letパターン)
 --> <anon>:2:8
  |
2 | if let x = 5 {
  |        ^ irrefutable pattern

このため、マッチアームは、論駁不可能なパターンで残りのあらゆる値に合致すべき最後のアームを除いて、 論駁可能なパターンを使用しなければなりません。コンパイラは、たった1つしかアームのないmatchで論駁不可能なパターンを使用させてくれますが、 この記法は特別有用なわけではなく、より単純なlet文に置き換えることもできるでしょう。

今やパターンを使用すべき箇所と論駁可能と論駁不可能なパターンの違いを知ったので、 パターンを生成するために使用できる全ての記法を講義しましょう。

関連キーワード:  パターン, 論駁, let, 合致, コード, Some, エラー, リスト, None, Rust