当Option为None或内部值满足某些条件时,做某事的惯用方法是什么



是否有更惯用的方式来表达以下内容?

fn main() {
let mut foo: Option<u8> = None;
match foo {
Some(foo_val) if ! (foo_val < 5) /* i.e. the negation of my acceptance condition */ => {}
_ => { foo.replace(5); }
}
}

大多数时候,似乎有一种替代方法可以让手臂什么都不做,但我一直找不到适合这种特殊情况的手臂。

我想说的是更直接的if foo.is_none() || /* some way to extract and test the inner value */ { ... },或者可能是一些逃避我的链接技巧

//        in None case
//             │       in Some(_) case
//            ┌┴─┐  ┌───────────────────┐    
if foo.map_or(true, |foo_val| foo_val < 5) {
// ...
}

有关详细信息,请参阅Option::map_or

有很多方法可以做到这一点。最简单(也可以说是最可读的(的方法是这样的:

if foo.unwrap_or(0) < 5 {
...
}

以上两种情况都适用:

  • foo是值小于5Some
  • 当CCD_ 6是CCD_

在一些更复杂的场景中;默认";需要计算值,并且性能至关重要,您可能需要考虑unwrap_or_else

正如Lukas所建议的,也可以使用map_or方法。请注意,传递给map_or的参数会被急切地评估,因此如果性能至关重要,您可能需要考虑将map_or_else作为一种替代方案。

锈蚀1.70+

CCD_ 12方法已在Rust 1.70中稳定。这里有一个例子:

if name.is_some_and(|s| s.len() > 50) {
println!("This is a long name!");
}

在许多情况下,它应该比map_or/map_or_else更可读。

您可以使用filter(使用条件的否定(和is_none:

if foo.filter(|&x| !(x < 5)).is_none() {
// Here either foo was None or it contained a value less than 5
}

我不确定我是否完全理解你的问题,但你可以尝试这样的方法:

fn main() {
let foo: Option<u8> = None;
let result = foo.filter(|foo_val| !(*foo_val < 5) ).unwrap_or(5);
println!("Result: {result}");
}

游乐场的更多示例

匹配!宏似乎很适合:

if matches!(foo, Some(a) if a>=5) { foo.replace(5) }

Rust Playground

我会加入另一个解决方案,只是为了好玩。。。。

foo = foo.
or(Some(5)). // if None return Some(5)
map(|x| if x<5 { 5 } else { x });

或者(对于这个特定的例子(

foo = foo.
or(Some(5)). // if None return Some(5)
map(|x| u8::max(x, 5));

使用filteror

foo = foo.filter(|a|  *a >= 5)
.or(Some(5));

由于Rust 1.70.0(2023-06-02(,可以使用Option::is_some_and。它是为与问题中相反的用例构建的:如果是None:,则返回false

if foo.is_some_and(|foo_val| foo_val < 5) { 
// ...
}

最新更新