Reputation: 4096
Rust has a construct called match
which looks very similar to switch
in other languages. However I observed a very peculiar behavior of match
.
let some_u32_value = 3;
match some_u32_value {
_ => (),
3 => println!("three"),
}
match
respects the order in which the cases/patterns are mentioned. Why does it not report an error if the default (_
) case is at the top? It does give a warning though:
warning: unreachable pattern
--> src/main.rs:5:9
|
5 | 3 => println!("three"),
| ^
|
= note: #[warn(unreachable_patterns)] on by default
A similar construct in Java, the switch, does not preserve any order, so having a default
prior to other cases is not an error (ignoring the fall through behavior).
int x = 0;
switch (x) {
default:
System.out.println("default");
break;
case 0:
System.out.println("Zero");
}
Is there some purpose for doing this explicitly?
Upvotes: 1
Views: 1609
Reputation: 42829
An unreachable pattern is not strictly an error, I mean: it does not prevent the compiler from "understanding" the code nor does it make the code unsafe.
Similarly, in C
, for example, you can return a reference to a local variable without triggering an error (at least with gcc
):
#include <stdio.h>
int* foo() {
int x = 0;
return &x;
}
int main() {
printf("%d", *foo());
return 0;
}
Generally, you should not consider a warning as "oh, that's only a warning, I don't care". A warning is an actual useful advice/information given by the compiler.
I like the definition given in warnings:
A warning is often issued on recognizing a potential high-risk situation, a probable misunderstanding, degraded service or imminent failure.
because it helps to understand the difference between an error and a warning:
In this situation, the last arm of the match
is some dead code, so the compiler reports it accordingly.
Upvotes: 6
Reputation: 58805
Rust's match
expressions are a lot more powerful than Java switch
statements, and you can do a lot more than just matching numbers.
In particular, it supports pattern matching which lets you match pieces of your data, based on either its structure or the values it contains. When you have more complex patterns to match, it's important to be able to specify the order because the patterns may overlap. For example:
let value = Some((Some(3), "hello"));
let s = match value {
None => "Nothing there!".to_owned(),
Some((Some(3), _)) => "The number is exactly 3!".to_owned(),
Some((Some(n), _)) if n > 3 => format!("Got a number bigger than 3: {}", n),
Some((None, msg)) => format!("Message with no number: {}", msg),
Some((_, msg)) => format!("Got the message, ignore the rest: {}", msg),
_ => "Anything else?".to_owned()
};
println!("result = {}", s);
The last case here is actually impossible because the other branches cover everything. The compiler will give a warning, in case that isn't what you intended.
Upvotes: 4