Skip to content

Commit daea9f4

Browse files
committed
Guide: match
1 parent c9e2ca0 commit daea9f4

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

src/doc/guide.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,102 @@ Enums
956956

957957
## Match
958958

959+
Often, a simple `if`/`else` isn't enough, because you have more than two
960+
possible options. And `else` conditions can get incredibly complicated. So
961+
what's the solution?
962+
963+
Rust has a keyword, `match`, that allows you to replace complicated `if`/`else`
964+
groupings with something more powerful. Check it out:
965+
966+
```rust
967+
let x = 5i;
968+
969+
match x {
970+
1 => println!("one"),
971+
2 => println!("two"),
972+
3 => println!("three"),
973+
4 => println!("four"),
974+
5 => println!("five"),
975+
_ => println!("something else"),
976+
}
977+
```
978+
979+
`match` takes an expression, and then branches based on its value. Each 'arm' of
980+
the branch is of the form `val => expression`. When the value matches, that arm's
981+
expression will be evaluated. It's called `match` because of the term 'pattern
982+
matching,' which `match` is an implementation of.
983+
984+
So what's the big advantage here? Well, there are a few. First of all, `match`
985+
does 'exhaustiveness checking.' Do you see that last arm, the one with the
986+
underscore (`_`)? If we remove that arm, Rust will give us an error:
987+
988+
```{ignore,notrust}
989+
error: non-exhaustive patterns: `_` not covered
990+
```
991+
992+
In other words, Rust is trying to tell us we forgot a value. Because `x` is an
993+
integer, Rust knows that it can have a number of different values. For example,
994+
`6i`. But without the `_`, there is no arm that could match, and so Rust refuses
995+
to compile. `_` is sort of like a catch-all arm. If none of the other arms match,
996+
the arm with `_` will. And since we have this catch-all arm, we now have an arm
997+
for every possible value of `x`, and so our program will now compile.
998+
999+
`match` statements also destructure enums, as well. Remember this code from the
1000+
section on enums?
1001+
1002+
```{rust}
1003+
let x = 5i;
1004+
let y = 10i;
1005+
1006+
let ordering = x.cmp(&y);
1007+
1008+
if ordering == Less {
1009+
println!("less");
1010+
} else if ordering == Greater {
1011+
println!("greater");
1012+
} else if ordering == Equal {
1013+
println!("equal");
1014+
}
1015+
```
1016+
1017+
We can re-write this as a `match`:
1018+
1019+
```{rust}
1020+
let x = 5i;
1021+
let y = 10i;
1022+
1023+
match x.cmp(&y) {
1024+
Less => println!("less"),
1025+
Greater => println!("greater"),
1026+
Equal => println!("equal"),
1027+
}
1028+
```
1029+
1030+
This version has way less noise, and it also checks exhaustively to make sure
1031+
that we have covered all possible variants of `Ordering`. With our `if`/`else`
1032+
version, if we had forgotten the `Greater` case, for example, our program would
1033+
have happily compiled. If we forget in the `match`, it will not. Rust helps us
1034+
make sure to cover all of our bases.
1035+
1036+
`match` is also an expression, which means we can use it on the right hand side
1037+
of a `let` binding. We could also implement the previous line like this:
1038+
1039+
```
1040+
let x = 5i;
1041+
let y = 10i;
1042+
1043+
let result = match x.cmp(&y) {
1044+
Less => "less",
1045+
Greater => "greater",
1046+
Equal => "equal",
1047+
};
1048+
1049+
println!("{}", result);
1050+
```
1051+
1052+
In this case, it doesn't make a lot of sense, as we are just making a temporary
1053+
string where we don't need to, but sometimes, it's a nice pattern.
1054+
9591055
## Looping
9601056

9611057
for

0 commit comments

Comments
 (0)