🦀

Rustの?演算子について

2023/11/27に公開

自己紹介

Rust言語を勉強している工学部理系大学生です.
ある程度Rust言語を理解した後,すぐにAxumを使用したwebアプリケーション開発を行いましたが,The bookの内容の重要性を感じ,再度勉強したいところを断片的に学んでいます.初心者のため間違っていたりしますが,ご容赦ください.

?演算子について

?演算子を実際に使用してみました.あえて2回使ったため,わかりずらくなってしまいました.

fn maybe_false()関数によって生成される0から10までの乱数で,その値が4の時にErrを返すコードでそれをfn check()でOkかErrかを判別してさらに fn main()関数で処理するコード になります.  
?演算子はエラーした時に責任をこの関数自身を包括しているスコープに譲渡しているようなイメージで理解しました. 誤解を恐れずにいうと責任放棄なのではないかと思いました. 最初の頃は.unrap()との違いがあまり理解できませんでした(どちらもOptionの値を取り出してくれるため)が.unrap()Errの時にpanicするので,そこに違いがあることを理解しました.

use std::error;
use rand::prelude::*;

fn main() {
    let judge = check();

    // check()関数がOKの場合はStringを返す.Errの場合はコマンドラインにエラーメッセージを表示する.
    match judge {
        Ok(i) => println!("{}", i),
        Err(err) => println!("{}", err),
    }
}


fn check() -> Result<String, Box<dyn error::Error>> {
    // Errorの場合はここで返される
    maybe_false()?;

    // エラーが譲渡されなかった場合はここにたどり着くので、Stringを返す
    let response = "We can pass".to_string();
    Ok(response)
}

// 0〜10の値をランダムに生成し,4だった場合はエラーになる関数
fn maybe_false() -> Result<(), Box<dyn error::Error>> {
    let mut rng = rand::thread_rng();
    let random_number = rng.gen_range(0 .. 11);

    // 4だったらErr, それ以外はOK(())
    let number = match random_number {
        4 => Err("this is poisoned number you took"),
        _ => Ok(()),
    };

    // ここではエラーハンドリングせず譲渡させる
    let number = number?;

    Ok(number)
}

出力は以下の通り

  • 生成された乱数が4ではなかった場合.
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/rust-relearn`
We can pass
  • 生成された乱数が4出あった場合.
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/rust-relearn`
this is poisoned number you took

Discussion