有没有更惯用的方式来表达如下内容?
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
为Some
且值小于5
时;foo
是None
时。在一些更复杂的场景中,需要计算“默认”值并且性能至关重要,您可能需要考虑
unwrap_or_else
。
map_or
方法。请注意,传递给 map_or
的参数会立即评估,因此如果性能至关重要,您可能需要考虑 map_or_else
作为替代方案。
is_some_and
方法已在 Rust 1.70 中稳定下来。这是一个例子:
if name.is_some_and(|s| s.len() > 50) {
println!("This is a long name!");
}
map_or
/ map_or_else
更具可读性。
自 Rust 1.70.0 (2023-06-02) 起,可以使用
Option::is_some_and
。它是为相反的用例构建的,如问题所示:如果是 false
,则返回 None
:
if foo.is_some_and(|foo_val| foo_val < 5) {
// ...
}
我不确定我完全理解你的问题,但你可以尝试这样的事情:
fn main() {
let foo: Option<u8> = None;
let result = foo.filter(|foo_val| !(*foo_val < 5) ).unwrap_or(5);
println!("Result: {result}");
}
更多示例请参阅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));
与
filter
和 or
,
foo = foo.filter(|a| *a >= 5)
.or(Some(5));