You don't need semicolons in match statements for the same reason that you don't need them at the end of a function when you want to return something. The comma is just for separating multiple cases in the match.
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
Note that this match actually produces a value. The value it produces is whatever the case it chose returns, so it's one of:
println!("Too small!")
println!("Too big!")
{ println!("You win!"); break; }
You may think these don't return anything, and in a sense they don't. However Rust has a type called unit, which is written like this: ()
and it is used as the return value of anything that doesn't return any value. In this case the println!
s don't return anything because println!
s just have no return value, and as for the block, it returns nothing because the last statement in the block has a semicolon.
In fact if you replace the break with a return of the value five, like this:
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
5
}
}
you get this error
error[E0308]: mismatched types
--> src/main.rs:12:13
|
7 | / match guess.cmp(&secret_number) {
8 | | Ordering::Less => println!("Too small!"),
9 | | Ordering::Greater => println!("Too big!"),
10 | | Ordering::Equal => {
11 | | println!("You win!");
12 | | 5
| | ^ expected (), found integer
13 | | }
14 | | }
| | -- help: consider using a semicolon here
| |_____|
| expected this to be `()`
|
= note: expected type `()`
found type `{integer}`
that says it expected the last match arm to return the unit type ()
because the other arms returned that type, and every arm in a match must return the same type.
If you take a look at this other match:
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
Then you will notice that it has a semicolon at the end. This is because the match is used as the value for the guess
variable, and the semicolon is there to end the let guess =
statement, not because of the match. Matches and if and loops are a bit of a special case because they allow skipping the semicolon when not used as a value.
As for what the match does, the first arm returns num
which has the type u32
and the other arm returns continue
. The continue
expression actually returns a special type called never, which is written using an exclamation mark. This type means that the expression never returns, and the compiler implicitly converts the never type to any other type, which is valid as the never type actually never happens (thus the name).
You can even make functions that return the never type. One example is std::process::abort
which never returns as it aborts the process.