Rustの疑問符演算子

Nilesh Katuwal 2023年6月21日
  1. Rust の疑問符演算子 (?)
  2. Rustでのエラーの伝播
  3. Rust で疑問符 (?) 演算子をいつ、どこで使用するか
Rustの疑問符演算子

このチュートリアルは、Rust の疑問符演算子 (?) についてです。

Rust の疑問符演算子 (?)

疑問符演算子 (?) は公正な値をアンラップし、呼び出し元の関数に誤った値を返します。これは呼び出し元に渡されます。 単項後置演算子は、Result<T, E> および Option<T> 型にのみ適用でき、他の型には使用できません。

一致演算子を使用して結果を連鎖させると、物事が混乱する可能性があります。 幸いなことに、? オペレーターは物事をもう少し整然とすることができます。 ? Result を返す式の最後で使用されます。

これは、Err(err) 分岐が初期の return Err(From::from(err)) に展開され、Ok(ok) 分岐が ok に展開される一致式と同等です。 式、および Err(err) 分岐は初期の return Err(From::from(err)) 分岐に展開されます。

? はオーバーロードできません。

お気づきかもしれませんが、Rust は規則に従う言語です。 したがって、パニックが含まれていますが、回復不能なエラーを対象としているため、エラー処理に使用することはお勧めしません。

さらに、? の使用方法を理解するために、エラーの伝播を研究する必要があります。 直接マークします。

Rustでのエラーの伝播

エラー伝搬とは、呼び出し元関数が問題を効果的に処理できるようにするために、呼び出し元関数によって呼び出されることが多いコードで見つかったエラー情報を伝搬または拡散する、または返すプロセスです。

例:

fn main() {
    let result = char_in_second_word(&"Learning when question mark used", &'i');

    println!("The value is {}", result.unwrap_or(1))
}


fn char_in_second_word(sentence: &str, char: &char) -> Option<usize> {
    let second_word =  match sentence.split(" ").next().is_some() == true {
        true => sentence.split(" ").next().unwrap(),
        false => return None
    };

    second_word.find(|x| &x == char)
}

出力:

The value is 5

シンプルなユーティリティ関数 char_in_second_word に注意してください。これは、リテラル文字列で検出された最初の単語で検出された文字のインデックスを返します。

ただし、文字列リテラルが Learning で、探している文字が I の場合、返されるインデックス値は Some(5) になります。これは、文字列リテラルの最初の単語が Learning であり、文字を含むためです。 I は文字配列の 5 の位置にあります。

しかし、疑問符を使用すると、コードをより簡単かつ単純にすることができます。

Rust では、Result はエラー処理に使用されます。 ? 演算子は、Result または Option を返す関数でのみ使用できます。

例:

use std::num::ParseIntError;

fn main() -> Result<(), ParseIntError>
{
    let num = "7".parse::<i32>()?;
    println!("{:?}", num);
    Ok(())
}

出力:

7

? 含まれる関数が Result も返す場合、演算子は Result 型で使用できます。

? が表示されるたびに、? が含まれている関数から早期に戻る可能性があることを示します。 利用されます。

Rust で疑問符 (?) 演算子をいつ、どこで使用するか

疑問符 ? を使用する状況がいくつかあります。 オペレーターは作成できません。 たとえば、説明には ? 演算子は、型 Result または Option を返す関数でのみ使用されます。

これは、関数内で Result および Option タイプを操作することを排除するものではありません。 ? 一方、演算子は、関数で同じ型を返す型で厳密に使用する必要があります。

つまり、関数が Result という名前の型を返す場合、? を使用します。 Result という名前の型の演算子。 関数が Option を返す場合、? 演算子は Option タイプで使用する必要があります。

? を使用しようとしています 2 種類のうちの 1つだけを返す関数で Result 型と Option 型の両方に演算子を使用すると、エラーが発生します。 説明のために、次のコードを検討してください。

fn err_fxn() -> Result<i32, String> {
    let x = Ok("The go!")?;
    let y = Some(1)?;

    Ok(x)
}

上記のソース コードを実行すると、次のようなエラーが発生します。

the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`

エラーの伝播では、? を覚えておく必要があります。 ショートカットとして使用されます。

もし ? 文字が関数によって返される型以外で使用されている場合、関数で定義されている型とは関係のない誤りが返される可能性があります。

幸いなことに、Rust はコンパイル プロセス中にこれらの問題をキャッチするのに十分なほどインテリジェントです。 その結果、コード実行中にそのようなミスは発生しません。