请考虑以下内容:
loop {
let data = match something() {
Err(err) => {
warn!("An error: {}; skipped.", err);
continue;
},
Ok(x) => x
};
let data2 = match something_else() {
Err(err) => {
warn!("An error: {}; skipped.", err);
continue;
},
Ok(x) => x
};
// and so on
}
如果我不需要给data
赋ok值,我会使用if let Err(err) = something()
,但是有没有一个捷径可以避免复制粘贴Err/Ok分支到上面的代码中,我想,典型的情况是这样的?类似于if let
,它也会返回ok值。
6条答案
按热度按时间swvgeqrz1#
虽然我认为E_net4的答案可能是最好的答案,但我还是添加了一个宏,以备将来创建一个单独的函数,并使用
?
操作符提前返回。下面是一个简单的
skip_fail!
宏,当传递一个错误时,continue
将成为一个包含循环:此宏可用作
let ok_value = skip_fail!(do_something());
Playground link which uses skip_fail to print out numbers divisible by 1, 2, and 3, and print an error when one of the divisions would truncate.
同样,我相信在一个单独的函数中使用
?
,如果没有失败,则返回Ok(end_result)
,这可能是最惯用的解决方案,所以如果可以使用该答案,您可能应该这样做。noj0wjuj2#
如果你经常要对结果进行“展开或继续”,可以考虑将这个逻辑封装在一个单独的函数中。这样,你就可以利用
?
语法来引发函数的错误。循环的流逻辑可以写在一个单独的地方(尽管此时你可能不再需要continue
)。pieyvz9o3#
如果必须将多个
Ok
链接在一起,需要在下一个操作中使用一个Ok
的值,并且不关心错误在链中的 * 何处 * 出现,请考虑and_then
:其中,
something
、something_else
、another_thing
和one_more
都返回某种形式的Result
。尽管本示例删除了continue
语句,但当Result
的类型为Err
时,and_then
通过短路有效地模拟了该语句。该行后面的所有调用都将被跳过。通过在只需要一次函数调用的语句中使用非闭包,可以使这一点更加简洁:
(Note函数上缺少括号,这表明它们被用作可调用对象,而不是获取其返回值)
5w9g7ksd4#
如果您愿意使用不稳定的特性,可以使用try块:
正如shepmaster在注解中提到的,这可以通过使用一个立即求值的闭包(一个立即调用的函数表达式,简称IIFE)来完成,而没有任何不稳定的特性。这是MutantOctopus在解决方案注解中对E_net4提出的解决方案的修改。
ruarlubt5#
Rust 1.65.0添加了
let-else
语句.所以你可以这样写:但您将无法访问
err
变量58wvjzkj6#
您可以使用我的unwrap_or板条箱来完成此操作。
您可以使用它来生成漂亮且干净的代码: