Early-breaking from Rust's match
Solution 1
You can wrap the match
into a loop
that only runs once and break out of the 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");
}
Solution 2
You could create a macro like
macro_rules! block {
($xs:block) => {
loop { break $xs }
};
}
and do
match x {
1 => block!({
...
if y == 0 { break; }
...
})
_ => {}
}
It's not an amazing solution, but it is semantically meaningful.
Solution 3
Something else you could do is make a "self-executing" closure and use a return statement inside. I don't know whether there are any weird performance characteristics of this but syntactically it's pretty clean.
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");
}
Here's a playground link showing it working.
ljrk
Pronouns: He/Him (Leo), They/Their or She/Her (Janis) https://keybase.io/larkey
Updated on June 04, 2022Comments
-
ljrk almost 2 years
I want to switch through many possible cases for
x
and there's one case (herex == 0
) where I want to check the result of some additional code to determine what to do next. One possibility is to return early from the match.I'd use
break
to do this early-returning in C, but this isn't allowed in Rust.return
returns from the parent function (in this casemain()
) and not from the match only (i.e. theprintln!
at the end isn't run!).I could just negate the sub-condition (here
y == 0
) and indent the whole lot of following code -- but I find this ugly and unreadable.Putting the sub-condition into a match-guard is no option for me since it's simply too big.
Is this possible in Rust or is there a better alternative (except creating another subfunction or other work-arounds)?
Minimal example:
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"); }
I found Mixing matching, mutation, and moves in Rust — is it wrong?
match
embraces both imperative and functional styles of programming: you can continue usingbreak
statements, assignments, et cetera, rather than being forced to adopt an expression-oriented mindset. -
ljrk almost 8 yearsThat's an interesting approach but I think rather obfuscates the idea more than it should and is not exactly an answer to my question. Have an upvote but I cannot accept it ;)
-
Shepmaster about 6 yearsany weird performance characteristics — there should not be as I expect this to be covered by Rust's "zero-cost abstractions".
-
don bright about 4 yearswhy doesn't it answer your question? it lets you break out of the match right? im asking because im porting a big C 1000+ line switch statement and this is pretty much how im dealing with breaking out of the middle of a match
-
otoomey about 3 years@donbright This solution works, but I think it's misleading code. If I came across it in the wild, I would have first assumed that the match is executed multiple times, when this is not the case. It would take me quite a while to figure this out, after which I would almost definitely try to refactor the
loop
statement out - assuming it to be a relic left by a previous fix. -
don bright about 3 yearsi get it now, thank you Camp bell. if i wasnt porting C i would never use this trick... i'd just rewrite it to make more sense in the first place.
-
Veedrac over 2 years@yolenoyer I believe my answer predates that syntax. I'll update.
-
Magix almost 2 yearsGreat idea, it reminds me of those javascript self-executing closure tricks to isolate parts of the code !