]> git.proxmox.com Git - rustc.git/blame - src/doc/trpl/match.md
Imported Upstream version 1.5.0+dfsg1
[rustc.git] / src / doc / trpl / match.md
CommitLineData
1a4d82fc
JJ
1% Match
2
bd371182
AL
3Often, a simple [`if`][if]/`else` isn’t enough, because you have more than two
4possible options. Also, conditions can get quite complex. Rust
5has a keyword, `match`, that allows you to replace complicated `if`/`else`
1a4d82fc
JJ
6groupings with something more powerful. Check it out:
7
9346a6ac 8```rust
1a4d82fc
JJ
9let x = 5;
10
11match x {
12 1 => println!("one"),
13 2 => println!("two"),
14 3 => println!("three"),
15 4 => println!("four"),
16 5 => println!("five"),
17 _ => println!("something else"),
18}
19```
20
bd371182
AL
21[if]: if.html
22
23`match` takes an expression and then branches based on its value. Each ‘arm’ of
9346a6ac
AL
24the branch is of the form `val => expression`. When the value matches, that arm’s
25expression will be evaluated. It’s called `match` because of the term ‘pattern
26matching’, which `match` is an implementation of. There’s an [entire section on
bd371182 27patterns][patterns] that covers all the patterns that are possible here.
1a4d82fc 28
9346a6ac
AL
29[patterns]: patterns.html
30
bd371182
AL
31So what’s the big advantage? Well, there are a few. First of all, `match`
32enforces ‘exhaustiveness checking’. Do you see that last arm, the one with the
1a4d82fc
JJ
33underscore (`_`)? If we remove that arm, Rust will give us an error:
34
35```text
36error: non-exhaustive patterns: `_` not covered
37```
38
39In other words, Rust is trying to tell us we forgot a value. Because `x` is an
bd371182
AL
40integer, Rust knows that it can have a number of different values – for
41example, `6`. Without the `_`, however, there is no arm that could match, and
42so Rust refuses to compile the code. `_` acts like a ‘catch-all arm’. If none
43of the other arms match, the arm with `_` will, and since we have this
44catch-all arm, we now have an arm for every possible value of `x`, and so our
45program will compile successfully.
1a4d82fc 46
1a4d82fc 47`match` is also an expression, which means we can use it on the right-hand
9346a6ac 48side of a `let` binding or directly where an expression is used:
1a4d82fc 49
9346a6ac
AL
50```rust
51let x = 5;
1a4d82fc 52
bd371182 53let number = match x {
9346a6ac
AL
54 1 => "one",
55 2 => "two",
56 3 => "three",
57 4 => "four",
58 5 => "five",
59 _ => "something else",
60};
1a4d82fc
JJ
61```
62
bd371182
AL
63Sometimes it’s a nice way of converting something from one type to another.
64
65# Matching on enums
66
67Another important use of the `match` keyword is to process the possible
68variants of an enum:
69
70```rust
71enum Message {
72 Quit,
73 ChangeColor(i32, i32, i32),
74 Move { x: i32, y: i32 },
75 Write(String),
76}
77
78fn quit() { /* ... */ }
79fn change_color(r: i32, g: i32, b: i32) { /* ... */ }
80fn move_cursor(x: i32, y: i32) { /* ... */ }
81
82fn process_message(msg: Message) {
83 match msg {
84 Message::Quit => quit(),
85 Message::ChangeColor(r, g, b) => change_color(r, g, b),
86 Message::Move { x: x, y: y } => move_cursor(x, y),
87 Message::Write(s) => println!("{}", s),
88 };
89}
90```
91
92Again, the Rust compiler checks exhaustiveness, so it demands that you
93have a match arm for every variant of the enum. If you leave one off, it
94will give you a compile-time error unless you use `_`.
95
96Unlike the previous uses of `match`, you can’t use the normal `if`
97statement to do this. You can use the [`if let`][if-let] statement,
98which can be seen as an abbreviated form of `match`.
99
d9579d0f 100[if-let]: if-let.html