我想切换x
的许多可能情况以及一个案例(此处x == 0
),我想检查一些其他代码的结果以确定下一步做什么。一种可能性是从比赛早期返回。
在C中,我使用break
进行早期返回,遗憾的是,这是不允许的。 return
从父函数(在本例中为main()
)返回,而不是仅从匹配中返回(即最后的println!
不运行!)。
我可以否定子条件(这里是y == 0
)并缩进以下代码 - 但我觉得这很难看且不可读。
将子条件放入比赛中并不是我的选择,因为它太大了。
这在Rust中是否可行,或者是否有更好的选择(除了创建另一个子功能或其他解决方法)?
最小例子:
fn main() {
let x = 1;
match x {
1 => {
let y = 0;
/*
* do ev1l stuff to y that I don't want to put into the match-guard
* as it's simply too much.
*/
/* break early ... */
if y == 0 {break;} // > error: `break` outside of loop [E0268]
assert!(y != 0, "y was 0!");
/* do other stuff in here. */
}
_ => {}
}
println!("done matching");
}
我发现这是最近的Rust blog post - 是不是错了?
match
包含命令式和函数式编程:您可以继续使用break
语句,赋值等,而不是被迫采用面向表达式的思维模式。
我还在学习Rust并且来自C所以请耐心等待我; - )
答案 0 :(得分:3)
您可以创建一个像
这样的宏macro_rules! block {
($xs:block) => {
loop { let _ = $xs; break; }
};
}
并做
match x {
1 => block!({
...
if y == 0 { break; }
...
})
_ => {}
}
这不是一个了不起的解决方案,但它具有语义意义。
答案 1 :(得分:2)
您可以将match
打包成只运行一次并突破循环的loop
fn main() {
let x = 1;
loop { match x {
1 => {
let y = 0;
/*
* do ev1l stuff to y that I don't want to put into the match-guard
* as it's simply too much.
*/
/* break early ... */
if y == 0 { break; }
assert!(y != 0, "y was 0!");
/* do other stuff in here. */
}
_ => {}
} break; }
println!("done matching");
}
答案 2 :(得分:2)
你可以做的其他事情是做一个自我执行的"关闭并在里面使用return语句。我不知道这是否有任何奇怪的性能特征,但在语法上它非常干净。
fn main() {
let x = 1;
// This closure is just used to catch the "return" statement.
(|| {
match x {
1 => {
let y = 0;
/*
* do ev1l stuff to y that I don't want to put into the match-guard
* as it's simply too much.
*/
/* break early ... */
if y == 0 { return; } // Ok!
assert!(y != 0, "y was 0!");
/* do other stuff in here. */
}
_ => {}
}
})();
println!("done matching");
}
这里有playground link显示它有效。