The question mark operator now supports Option
, so you can write your function as
fn do_something(a: i32) -> Option<i32> {
let b = f(a)?;
let c = g(b)?;
let d = h(c)?;
do_something_with(a, b, c, d) // wrap in Some(...) if this doesn't return an Option
}
Rust 1.0
The Rust standard library defines a try!
macro (and, equivalently, the ?
operator, as of Rust 1.13) that solves this problem for Result
. The macro looks like this:
macro_rules! try {
($expr:expr) => (match $expr {
$crate::result::Result::Ok(val) => val,
$crate::result::Result::Err(err) => {
return $crate::result::Result::Err($crate::convert::From::from(err))
}
})
}
If the argument is Err
, it returns from the function with that Err
value. Otherwise, it evaluates to the value wrapped in Ok
. The macro can only be used in a function that returns Result
, because it returns the error it meets.
We can make a similar macro for Option
:
macro_rules! try_opt {
($expr:expr) => (match $expr {
::std::option::Option::Some(val) => val,
::std::option::Option::None => return None
})
}
You can then use this macro like this:
fn do_something(a: i32) -> Option<i32> {
let b = try_opt!(f(a));
let c = try_opt!(g(b));
let d = try_opt!(h(c));
do_something_with(a, b, c, d) // wrap in Some(...) if this doesn't return an Option
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…