]> git.proxmox.com Git - rustc.git/blob - src/doc/book/match.md
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / doc / book / match.md
1 % Match
2
3 Often, a simple [`if`][if]/`else` isn’t enough, because you have more than two
4 possible options. Also, conditions can get quite complex. Rust
5 has a keyword, `match`, that allows you to replace complicated `if`/`else`
6 groupings with something more powerful. Check it out:
7
8 ```rust
9 let x = 5;
10
11 match 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
21 [if]: if.html
22
23 `match` takes an expression and then branches based on its value. Each ‘arm’ of
24 the branch is of the form `val => expression`. When the value matches, that arm’s
25 expression will be evaluated. It’s called `match` because of the term ‘pattern
26 matching’, which `match` is an implementation of. There’s a [separate section on
27 patterns][patterns] that covers all the patterns that are possible here.
28
29 [patterns]: patterns.html
30
31 One of the many advantages of `match` is it enforces ‘exhaustiveness checking’.
32 For example if we remove the last arm with the underscore `_`, the compiler will
33 give us an error:
34
35 ```text
36 error: non-exhaustive patterns: `_` not covered
37 ```
38
39 Rust is telling us that we forgot some value. The compiler infers from `x` that it
40 can have any 32bit integer value; for example -2,147,483,648 to 2,147,483,647. The `_` acts
41 as a 'catch-all', and will catch all possible values that *aren't* specified in
42 an arm of `match`. As you can see in the previous example, we provide `match`
43 arms for integers 1-5, if `x` is 6 or any other value, then it is caught by `_`.
44
45 `match` is also an expression, which means we can use it on the right-hand
46 side of a `let` binding or directly where an expression is used:
47
48 ```rust
49 let x = 5;
50
51 let number = match x {
52 1 => "one",
53 2 => "two",
54 3 => "three",
55 4 => "four",
56 5 => "five",
57 _ => "something else",
58 };
59 ```
60
61 Sometimes it’s a nice way of converting something from one type to another; in
62 this example the integers are converted to `String`.
63
64 # Matching on enums
65
66 Another important use of the `match` keyword is to process the possible
67 variants of an enum:
68
69 ```rust
70 enum Message {
71 Quit,
72 ChangeColor(i32, i32, i32),
73 Move { x: i32, y: i32 },
74 Write(String),
75 }
76
77 fn quit() { /* ... */ }
78 fn change_color(r: i32, g: i32, b: i32) { /* ... */ }
79 fn move_cursor(x: i32, y: i32) { /* ... */ }
80
81 fn process_message(msg: Message) {
82 match msg {
83 Message::Quit => quit(),
84 Message::ChangeColor(r, g, b) => change_color(r, g, b),
85 Message::Move { x: x, y: y } => move_cursor(x, y),
86 Message::Write(s) => println!("{}", s),
87 };
88 }
89 ```
90
91 Again, the Rust compiler checks exhaustiveness, so it demands that you
92 have a match arm for every variant of the enum. If you leave one off, it
93 will give you a compile-time error unless you use `_` or provide all possible
94 arms.
95
96 Unlike the previous uses of `match`, you can’t use the normal `if`
97 statement to do this. You can use the [`if let`][if-let] statement,
98 which can be seen as an abbreviated form of `match`.
99
100 [if-let]: if-let.html