map_or()
,将Some(_)
转换为Err(666)
,将None
转换为Ok(())
。但是,这不是惯用法,我个人也会坚持使用if is_some() { return Err(666); }
,因为这样做更清晰易懂。fn foo(o: Option<i32>) -> Result<(), i32> {
o.map_or(Ok(()), |_| Err(666))?;
Ok(())
}
fn main() {
println!("{:?}", foo(None));
println!("{:?}", foo(Some(42)));
}
输出:
Ok(())
Err(666)
trait ErrOnSome {
fn err_on_some<F, E>(&self, f: F) -> Result<(), E>
where
F: FnOnce() -> Result<(), E>;
}
impl<T> ErrOnSome for Option<T> {
fn err_on_some<F, E>(&self, f: F) -> Result<(), E>
where
F: FnOnce() -> Result<(), E>,
{
match self {
None => Ok(()),
Some(_) => f(),
}
}
}
fn foo(o: Option<i32>) -> Result<(), i32> {
o.err_on_some(|| Err(666))?;
Ok(())
}
main()
,它当然会产生相同的输出。
编辑:旧答案 - 我误读并认为它是关于返回Option
的
如果包含的值是一个原始值,即便宜创建,则可以坚持使用xor()
。但是,这不是惯用法,我个人也会坚持使用if is_some() { return Err(666); }
,因为这样做对读者更清晰明了。
fn foo(o: Option<i32>) -> Option<()> {
o.xor(Some(666))?;
Some(())
}
fn main() {
println!("{:?}", foo(None));
println!("{:?}", foo(Some(42)));
}
输出:
Some(123)
None
?
,在Some
上返回Err
?Option :: map
将选项的 Some 变体映射为 Err 。 这将将 Option&lt; T&gt; 转换为 Option&lt; Result&lt; X,E&gt;> ,您可以将其转置为 Result&lt; Option&lt; X&gt;,E&gt; 并在其上使用?
:
fn x() -> Result<(), i32> {
let o = Some(42);
o.map(|_| Err::<(), _>(666)).transpose()?;
Ok(())
}
Err
中的 turbofish 提供了必要的类型提示,否则 Rust 就无法确定上述 Result<X, E>
中的 X
,而结果必须同时具有 ok 和 error 类型。我选择了 ()
,但它与函数返回类型中的 ()
毫不相关;因为 ?
运算符仅关心 Result
的错误类型,所以它可以是任何其他类型。请注意保留 HTML 标签。