我有一个
while let
循环,它遍历 Result
的迭代器并使用模式匹配;它会遍历迭代器,直到遇到 Err
或 Ok
的值为空字符串:
while let Some(Ok(a)) = some_iterator.next() {
if a == "" {
break;
}
// ...
}
这段代码运行良好。然而,我认为
if
语句看起来很难看,并且可能不是惯用的 Rust。在 match
语句中,守卫可以用于模式匹配,如下所示:
match foo {
Some(Ok(a)) if a != "" => bar(a)
// ...
}
这对于我的
while let
循环来说是理想的选择,尽管那里使用的模式匹配似乎不支持它,导致语法错误:
while let Some(Ok(a)) = some_iterator.next() if a != "" { // <-- Syntax error
// ...
}
在
while let
的情况下有没有办法使用这样的守卫?如果没有,如果找到空字符串,是否有更好的方法来跳出循环?
不可以,
while let
和if let
模式不能有防护装置。已经有一些关于改变这一点的讨论(例如here),但尚未做出任何决定。
关于替代方案,我认为你的版本非常清楚,我想不出任何方法可以真正改进它。
对于那些从网络搜索中找到此内容的人,这里有
if-let-chains
RFC,它解决了 if let
表达式中的条件:
无论出于何种意图和目的,您的代码都是最清晰的。
但是您可以发挥创意(包括使用在询问时不可用的工具)。
将条件塞入模式匹配中:
while let (Some(a), true) = (iterator.next(), independent_condition()) {
//do stuff
}
将过滤器放入迭代器中:
while let Some(a) = iterator.take_while(|a| a!= "").next() {
//do stuff
}
请记住,在简单的情况下,当您最终得到一个迭代器时,您不再需要模式解构:
for a in iterator.take_while(|a| a!= "") {
//do stuff
}
skip_while 和 scan 是迭代器上类似的高级方法,在这种情况下可能会派上用场。