Result
We've seen that the Option
enum can be used as a return value from functions that may fail, where None
can be returned to indicate failure. However, sometimes it is important to express why an operation failed. To do this we have the Result
enum.
列挙型Result<T, E>
は2つの値をとりえます。
Ok(value)
... これはオペレーションが成功したことを意味し、返り値value
をラップします。(value
は型T
を持ちます。)Err(why)
... これはオペレーションの失敗を意味します。why
をラップしており、ここには失敗した理由が(必ずではありませんが)書かれています。(why
の型はE
です。)
mod checked { // 捕捉対象としたい、数学的な「エラー」 #[derive(Debug)] pub enum MathError { DivisionByZero, NonPositiveLogarithm, NegativeSquareRoot, } pub type MathResult = Result<f64, MathError>; pub fn div(x: f64, y: f64) -> MathResult { if y == 0.0 { // 分母が0なので、このオペレーションは普通に行えば失敗します。 // 代わりに`Err`でラップされた失敗の理由を返しましょう。 Err(MathError::DivisionByZero) } else { // このオペレーションは問題がないので、 // 結果を`Ok`でラップして返しましょう。 Ok(x / y) } } pub fn sqrt(x: f64) -> MathResult { if x < 0.0 { Err(MathError::NegativeSquareRoot) } else { Ok(x.sqrt()) } } pub fn ln(x: f64) -> MathResult { if x <= 0.0 { Err(MathError::NonPositiveLogarithm) } else { Ok(x.ln()) } } } // `op(x, y)` === `sqrt(ln(x / y))` fn op(x: f64, y: f64) -> f64 { // 3段階の`match`ピラミッド! match checked::div(x, y) { Err(why) => panic!("{:?}", why), Ok(ratio) => match checked::ln(ratio) { Err(why) => panic!("{:?}", why), Ok(ln) => match checked::sqrt(ln) { Err(why) => panic!("{:?}", why), Ok(sqrt) => sqrt, }, }, } } fn main() { // これは失敗するでしょうか? println!("{}", op(1.0, 10.0)); }