1. ホーム
  2. rust

[解決済み] このクエスチョンマークの演算子は何についてですか?

2022-04-21 07:34:33

質問

今読んでいる本 のドキュメントを参照してください。 File :

//..
let mut file = File::create("foo.txt")?;
//..

とは何ですか? ? この行の 以前、Rust Bookで見た記憶がないのですが。

どのように解決するのですか?

お気づきかもしれませんが、Rustには例外がありません。パニックはありますが、エラー処理に使うことは推奨されません(回復不能なエラーに使われるものです)。

Rust では、エラー処理には Result . 典型的な例としては、次のようなものがあります。

fn halves_if_even(i: i32) -> Result<i32, Error> {
    if i % 2 == 0 {
        Ok(i / 2)
    } else {
        Err(/* something */)
    }
}

fn do_the_thing(i: i32) -> Result<i32, Error> {
    let i = match halves_if_even(i) {
        Ok(i) => i,
        Err(e) => return Err(e),
    };

    // use `i`
}

これは素晴らしいことです。

  • コードを書くときに、誤ってエラーに対処するのを忘れてしまうことがない。
  • コードを読むと、ここにエラーの可能性があることがすぐにわかります。

しかし、非常に冗長であるという点では、理想的とは言えません。そこで、クエスチョンマーク演算子 ? の出番です。

上記は次のように書き換えることができる。

fn do_the_thing(i: i32) -> Result<i32, Error> {
    let i = halves_if_even(i)?;

    // use `i`
}

の方がはるかに簡潔です。

? がここで行うのは match の文は、上記の文に追加を加えたものです。要するに

  1. を解凍します。 Result OKなら
  2. それは を返します。 を呼び出すと、エラーが発生します。 Into::into を使用して、エラー値を別の型に変換することができます。

例外処理とは異なり、どの関数コールがエラーになるのか、ならないのかが一目瞭然です。 ? .

マジックの一例として、これは以下のものにも有効です。 Option :

// Assume
// fn halves_if_even(i: i32) -> Option<i32>

fn do_the_thing(i: i32) -> Option<i32> {
    let i = halves_if_even(i)?;

    // use `i`
}

? 演算子を使用します。 は、Rust バージョン 1.13.0 で安定化しました。 は、(不安定な) Try トライブがあります。

こちらもご覧ください。