Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

エラー時に消費された引数を返す

説明

失敗しうる関数が引数を消費(ムーブ)する場合、その引数を エラーの中で返します。

pub fn send(value: String) -> Result<(), SendError> {
    println!("using {value} in a meaningful way");
    // 非決定的な失敗しうるアクションをシミュレートします。
    use std::time::SystemTime;
    let period = SystemTime::now()
        .duration_since(SystemTime::UNIX_EPOCH)
        .unwrap();
    if period.subsec_nanos() % 2 == 1 {
        Ok(())
    } else {
        Err(SendError(value))
    }
}

pub struct SendError(String);

fn main() {
    let mut value = "imagine this is very long string".to_string();

    let success = 's: {
        // value の送信を 2 回試みます。
        for _ in 0..2 {
            value = match send(value) {
                Ok(()) => break 's true,
                Err(SendError(value)) => value,
            }
        }
        false
    };

    println!("success: {success}");
}

動機

エラーの場合、別の方法を試したり、非決定的な関数の場合にはアクションを再試行したりしたいことがあります。しかし、引数が常に消費される場合、呼び出しのたびにそれをクローンせざるを得ず、これはあまり効率的ではありません。

標準ライブラリでは、たとえば String::from_utf8 メソッドでこのアプローチを使用しています。有効な UTF-8 を含まないベクターを渡すと、FromUtf8Error が返されます。FromUtf8Error::into_bytes メソッドを使用して、元のベクターを取り戻すことができます。

利点

可能な限り引数をムーブするため、パフォーマンスが向上します。

欠点

エラー型がやや複雑になります。