如果遇到None,我们可以使用or_else和?提前返回Err:
None
or_else
?
Err
let o = None; let x = o.ok_or(666)?;
但是如果我们期望相反的结果呢?如果某个东西是Some,那么就早点返回:
Some
let o = Some(42); if o.is_some() { return Err(666); }
我们能用?也做到这一点吗?
czfnxgou1#
我想这一切都是为了让它成为单行并节省字符。你可以使用map_or(),把Some(_)转换成Err(666),把None转换成Ok(()),但是,这不是惯用的,我个人还是坚持使用if is_some() { return Err(666); },因为它的作用对读者来说更清楚。
map_or()
Some(_)
Err(666)
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)
你也可以创建你自己的ErrOnSome trait,把这个方法命名为err_on_some(),这样读者就可以更清楚地了解它的作用,即使你不知道err_on_some()方法的实现。
ErrOnSome
err_on_some()
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
如果包含的值是一个原语,即 * create * 便宜,那么你可以坚持使用xor(),但是,这不是惯用的,我个人也坚持使用if is_some() { return Err(666); },因为读者更清楚它的作用。
xor()
fn foo(o: Option<i32>) -> Option<()> { o.xor(Some(666))?; Some(()) } fn main() { println!("{:?}", foo(None)); println!("{:?}", foo(Some(42))); }
Some(123) None
qojgxg4l2#
我们是否可以用某种方法[在Some上返回Err]同时返回??我不会称之为 idiomatic,但是你可以使用Option::map将选项的Some变体Map为Err,这会将Option<T>转换为Option<Result<X, E>>,你可以将其转换为Result<Option<X>, E>,然后使用?:
Option::map
Option<T>
Option<Result<X, E>>
Result<Option<X>, E>
fn x() -> Result<(), i32> { let o = Some(42); o.map(|_| Err::<(), _>(666)).transpose()?; Ok(()) }
Err上的turbofish提供了一个必要的类型提示,否则Rust无法确定上面提到的Result<X, E>的X,结果必须同时有ok和error类型,我选择了(),但它与函数返回类型中的()完全无关;它可以是任何其它类型,因为X1 M15 N1 X运算符只关心X1 M16 N1 X的错误类型。
Result<X, E>
X
()
2条答案
按热度按时间czfnxgou1#
我想这一切都是为了让它成为单行并节省字符。
你可以使用
map_or()
,把Some(_)
转换成Err(666)
,把None
转换成Ok(())
,但是,这不是惯用的,我个人还是坚持使用if is_some() { return Err(666); }
,因为它的作用对读者来说更清楚。输出:
你也可以创建你自己的
ErrOnSome
trait,把这个方法命名为err_on_some()
,这样读者就可以更清楚地了解它的作用,即使你不知道err_on_some()
方法的实现。main()
,当然会产生相同的输出。*Option
的如果包含的值是一个原语,即 * create * 便宜,那么你可以坚持使用
xor()
,但是,这不是惯用的,我个人也坚持使用if is_some() { return Err(666); }
,因为读者更清楚它的作用。输出:
qojgxg4l2#
我们是否可以用某种方法[在
Some
上返回Err
]同时返回?
?我不会称之为 idiomatic,但是你可以使用
Option::map
将选项的Some
变体Map为Err
,这会将Option<T>
转换为Option<Result<X, E>>
,你可以将其转换为Result<Option<X>, E>
,然后使用?
:Err
上的turbofish提供了一个必要的类型提示,否则Rust无法确定上面提到的Result<X, E>
的X
,结果必须同时有ok和error类型,我选择了()
,但它与函数返回类型中的()
完全无关;它可以是任何其它类型,因为X1 M15 N1 X运算符只关心X1 M16 N1 X的错误类型。