Menu
Coddy logo textTech

クエスチョンマーク演算子 '?'

CoddyのRustジャーニー「Logic & Flow」セクションの一部 — レッスン 46/66。

Resultを返す関数を扱う際、ローカルでエラーを処理するか、呼び出し元の関数にエラーを渡すことで、エラーを処理する必要が頻繁にあります。Rustは、この一般的なパターンに対してエレガントな演算子を提供しています。それがクエスチョンマーク演算子 ? です。

? 演算子は、冗長な match 文を書くことなく、エラーを伝播させるためのクリーンな方法を提供します。Result の後に ? を置くと、自動的に Ok の値をアンラップするか、または Err を伴って現在の関数から即座にリターンします。

fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
    let number = s.parse::<i32>()?; // パースに失敗した場合は、エラーを返す
    Ok(number * 2) // 成功した場合は、数値を2倍にする
}

これは、完全な match 文を書くのと同等ですが、ずっと簡潔です。もし s.parse::<i32>()Ok を返す場合、? はその値を抽出し、number に代入します。もし Err を返す場合は、? は即座にそのエラーを関数全体から返します。

? 演算子は、エラーを返す必要があるため、Result(または Option)を返す関数内でのみ使用できます。

challenge icon

チャレンジ

簡単

2つの入力を受け取ります。最初の入力は整数にパースされるべき文字列で、2番目の入力も同様に整数にパースされるべき文字列です。2つの文字列スライスをパラメータとして受け取り、Result<i32, std::num::ParseIntError>を返すadd_numbersという関数を作成してください。関数内では、?演算子を使用して両方の文字列をパースし、それらの合計をOkで包んで返します。2つの入力を使用してこの関数を呼び出し、matchを使用して結果を処理してください。

要件:

  • 最初の入力(文字列としての最初の数値)を読み込み、空白をトリミングする
  • 2番目の入力(文字列としての2番目の数値)を読み込み、空白をトリミングする
  • 2つの&strパラメータを受け取り、Result<i32, std::num::ParseIntError>を返す関数add_numbersを作成する
  • 関数内で、?演算子を使用して最初の文字列をi32にパースする
  • ?演算子を使用して2番目の文字列をi32にパースする
  • パースされた両方の数値の合計であるOk(sum)を返す
  • 2つの入力文字列を使用して関数を呼び出す
  • match式を使用してResultを処理する
  • Ok(value)アームでは、Sum: [value]と出力する
  • Err(_)アームでは、Parsing errorと出力する

入力:

  • 1行目: 数値を表す文字列 (例: 15)
  • 2行目: 別の数値を表す文字列 (例: 27)

出力:

  • 両方の文字列が有効な数値の場合: Sum: [result]
  • いずれかの文字列がパースできない場合: Parsing error

チートシート

クエスチョンマーク演算子 ? は、Result を返す関数においてエラーを伝播させるための簡潔な方法を提供します。

Result の後に置かれた場合、? 演算子は以下の動作をします:

  • Ok 値をアンラップして実行を継続する
  • エラーが発生した場合は、現在の関数から即座に Err を返す
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
    let number = s.parse::<i32>()?; // パースに失敗した場合は、エラーを返す
    Ok(number * 2) // 成功した場合は、数値を2倍にする
}

? 演算子は、Result または Option 型を返す関数内でのみ使用できます。

自分で試してみよう

use std::io;

// TODO: ここにadd_numbers関数を作成してください
// 2つの&strパラメータを受け取り、Result<i32, std::num::ParseIntError>を返す必要があります


fn main() {
    // 最初の入力を読み込む
    let mut input1 = String::new();
    io::stdin().read_line(&mut input1).expect("Failed to read line");
    let input1 = input1.trim();
    
    // 2番目の入力を読み込む
    let mut input2 = String::new();
    io::stdin().read_line(&mut input2).expect("Failed to read line");
    let input2 = input2.trim();
    
    // TODO: input1とinput2を使用してadd_numbersを呼び出す
    // TODO: matchを使用してResultを処理する
    // Ok(value)の場合は "Sum: [value]" を出力する
    // Err(_)の場合は "Parsing error" を出力する
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

Logic & Flowのすべてのレッスン