5 ms·
I didn't understand his comment on Rust's match expression. Other than it returning a value (and insisting a default clause) it's just like C's switch, right?
by luckydude 10y ago
I didn't understand his comment on Rust's match expression.
Other than it returning a value (and insisting a default clause) it's just like C's switch, right?
- fjh 10y agomatch also lets you destructure values, which is useful when you're dealing with enums. It also doesn't have C's fall-through behaviour. Edit: match doesn't insist on a default clause, it enforces exhaustiveness. Which can be achieved by having a default clause, but quite often you just have an explicit branch for every possible case.
- Tarean 10y agoIt is much more like haskell's pattern matching. Notably it handles tagged unions (in rust enum). Here is a good example from the [book](https://doc.rust-lang.org/book/match.html https://doc.rust-lang.org/book/match.html): enum Message { Quit, ChangeColor(i32, i32, i32), Move { x: i32, y: i32 }, Write(String), } fn quit() { /* ... */ } fn change_color(r: i32, g: i32, b: i32) { /* ... */ } fn move_cursor(x: i32, y: i32) { /* ... */ } fn process_message(msg: Message) { match msg { Message::Quit => quit(), Message::ChangeColor(r, g, b) => change_color(r, g, b), Message::Move { x: x, y: y } => move_cursor(x, y), Message::Write(s) => println!("{}", s), }; }
- kibwen 10y agoDifferences from C's switch: 1. No fallthrough-by-default. 2. Checked for exhaustiveness. This is different from "insisting on a default clause", because if you see a match with no default clause, then you know that the compiler is verifying that every possible case is being handled. 3. The cases of the match can be arbitrary patterns, not just integers. This allows you to perform very natural and powerful conditional control flow, especially when using tagged unions. 4. Can return a value. Finally, remember the context of this post: Python doesn't have a C-style switch statement at all. :P
- deleted 10y ago[deleted]
- masklinn 10y ago> and insisting a default clause It does not insist on a default clause it requires match completeness, which depending on the matched value may require a default clause (e.g. it does for integrals[0], it does not for enums as you can match each case individually) > it's just like C's switch, right? Only in its most simplistic form (though even then it does not ever fall through — whether by default or optionally — is type-safe and requires match-completeness), match performs refutable pattern matching on possibly complex values and allows additional per-match conditionals. match foo { // complex destructuring and multiple patterns for a case Some((42, _)) | Some((55, _)) => { println!("1") } // simple destructuring + conditional Some(a) if a.0 % 5 == 0 => { println!("2") } // matching + wildcard Some(..) => { println!("3") } // trivial matching None => { println!("4") } } or match (i % 3, i % 5) { (0, 0) => {} (0, _) => {} (_, 0) => {} _ => {} } [0] because the completeness checking doesn't really handle non-enum values currently
- stonemetal 10y agoYou can also have guards in rust's match expression. They must be bool a typed expression but other than that they can be as complex as necessary.
- stormbrew 10y agoAll the other answers are correct, in so far as they go, but they kind of fail to explain the bigger picture imo. A match statement like rust has is part of a larger concept where types are an integral part of control flow. C/C++ switch makes no assertion about what is or isn't valid in its branches. That is, you might be switching on a tag field of a union or something like that, and then in one (or more) of the switch branches you may act on that information. But there is no compiler constraint on the correctness of that decision. Pattern matching insists that the code inside a particular branch matches the type expectations asserted in its case clause. If you're in the branch for enum-type Blah, you can only act on Blah and not on Blorp. The compiler will force this on you. To put this in practical terms, one area I have found this incredibly valuable (in Swift, but it applies here too) is in state machines. If you represent your state machine as an enum/union with fields for the information any particular state needs, every iteration through the machine you can be sure you are acting on the correct information. The compiler won't let you do otherwise.
- tedmielczarek 10y agoI think other commenters have explained it pretty well, but suffice to say that if you get comfortable writing Rust you grow to really like using match, and most languages don't have an equivalent. :)
- contras1970 10y agoit's just like C's switch, right? not at all, absolutely not. consider: switch (count % 8) { case 0: do { *to = *from++; case 7: *to = *from++; case 6: *to = *from++; case 5: *to = *from++; case 4: *to = *from++; case 3: *to = *from++; case 2: *to = *from++; case 1: *to = *from++; } while (--n > 0); } https://en.wikipedia.org/wiki/Duff's_device https://en.wikipedia.org/wiki/Duff's_device