1
1
% Match
2
2
3
- Often, a simple ` if ` /` else ` isn' t enough, because you have more than two
3
+ Often, a simple ` if ` /` else ` isn’ t enough, because you have more than two
4
4
possible options. Also, ` else ` conditions can get incredibly complicated, so
5
- what' s the solution?
5
+ what’ s the solution?
6
6
7
7
Rust has a keyword, ` match ` , that allows you to replace complicated ` if ` /` else `
8
8
groupings with something more powerful. Check it out:
9
9
10
- ``` { rust}
10
+ ``` rust
11
11
let x = 5 ;
12
12
13
13
match x {
@@ -21,11 +21,14 @@ match x {
21
21
```
22
22
23
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.
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 an [ entire section on
27
+ patterns] [ patterns ] coming up next, that covers all the options that fit here.
27
28
28
- So what's the big advantage here? Well, there are a few. First of all, ` match `
29
+ [ patterns ] : patterns.html
30
+
31
+ So what’s the big advantage here? Well, there are a few. First of all, ` match `
29
32
enforces * exhaustiveness checking* . Do you see that last arm, the one with the
30
33
underscore (` _ ` )? If we remove that arm, Rust will give us an error:
31
34
@@ -36,121 +39,24 @@ error: non-exhaustive patterns: `_` not covered
36
39
In other words, Rust is trying to tell us we forgot a value. Because ` x ` is an
37
40
integer, Rust knows that it can have a number of different values – for example,
38
41
` 6 ` . Without the ` _ ` , however, there is no arm that could match, and so Rust refuses
39
- to compile. ` _ ` acts like a * catch-all arm* . If none of the other arms match,
42
+ to compile. ` _ ` acts like a ‘ catch-all arm’ . If none of the other arms match,
40
43
the arm with ` _ ` will, and since we have this catch-all arm, we now have an arm
41
44
for every possible value of ` x ` , and so our program will compile successfully.
42
45
43
- ` match ` statements also destructure enums, as well. Remember this code from the
44
- section on enums?
45
-
46
- ``` {rust}
47
- use std::cmp::Ordering;
48
-
49
- fn cmp(a: i32, b: i32) -> Ordering {
50
- if a < b { Ordering::Less }
51
- else if a > b { Ordering::Greater }
52
- else { Ordering::Equal }
53
- }
54
-
55
- fn main() {
56
- let x = 5;
57
- let y = 10;
58
-
59
- let ordering = cmp(x, y);
60
-
61
- if ordering == Ordering::Less {
62
- println!("less");
63
- } else if ordering == Ordering::Greater {
64
- println!("greater");
65
- } else if ordering == Ordering::Equal {
66
- println!("equal");
67
- }
68
- }
69
- ```
70
-
71
- We can re-write this as a ` match ` :
72
-
73
- ``` {rust}
74
- use std::cmp::Ordering;
75
-
76
- fn cmp(a: i32, b: i32) -> Ordering {
77
- if a < b { Ordering::Less }
78
- else if a > b { Ordering::Greater }
79
- else { Ordering::Equal }
80
- }
81
-
82
- fn main() {
83
- let x = 5;
84
- let y = 10;
85
-
86
- match cmp(x, y) {
87
- Ordering::Less => println!("less"),
88
- Ordering::Greater => println!("greater"),
89
- Ordering::Equal => println!("equal"),
90
- }
91
- }
92
- ```
93
-
94
- This version has way less noise, and it also checks exhaustively to make sure
95
- that we have covered all possible variants of ` Ordering ` . With our ` if ` /` else `
96
- version, if we had forgotten the ` Greater ` case, for example, our program would
97
- have happily compiled. If we forget in the ` match ` , it will not. Rust helps us
98
- make sure to cover all of our bases.
99
-
100
- ` match ` expressions also allow us to get the values contained in an ` enum `
101
- (also known as destructuring) as follows:
102
-
103
- ``` {rust}
104
- enum OptionalInt {
105
- Value(i32),
106
- Missing,
107
- }
108
-
109
- fn main() {
110
- let x = OptionalInt::Value(5);
111
- let y = OptionalInt::Missing;
112
-
113
- match x {
114
- OptionalInt::Value(n) => println!("x is {}", n),
115
- OptionalInt::Missing => println!("x is missing!"),
116
- }
117
-
118
- match y {
119
- OptionalInt::Value(n) => println!("y is {}", n),
120
- OptionalInt::Missing => println!("y is missing!"),
121
- }
122
- }
123
- ```
124
-
125
- That is how you can get and use the values contained in ` enum ` s.
126
- It can also allow us to handle errors or unexpected computations; for example, a
127
- function that is not guaranteed to be able to compute a result (an ` i32 ` here)
128
- could return an ` OptionalInt ` , and we would handle that value with a ` match ` .
129
- As you can see, ` enum ` and ` match ` used together are quite useful!
130
-
131
46
` match ` is also an expression, which means we can use it on the right-hand
132
- side of a ` let ` binding or directly where an expression is used. We could
133
- also implement the previous example like this:
134
-
135
- ``` {rust}
136
- use std::cmp::Ordering;
47
+ side of a ` let ` binding or directly where an expression is used:
137
48
138
- fn cmp(a: i32, b: i32) -> Ordering {
139
- if a < b { Ordering::Less }
140
- else if a > b { Ordering::Greater }
141
- else { Ordering::Equal }
142
- }
143
-
144
- fn main() {
145
- let x = 5;
146
- let y = 10;
49
+ ``` rust
50
+ let x = 5 ;
147
51
148
- println!("{}", match cmp(x, y) {
149
- Ordering::Less => "less",
150
- Ordering::Greater => "greater",
151
- Ordering::Equal => "equal",
152
- });
153
- }
52
+ let numer = match x {
53
+ 1 => " one" ,
54
+ 2 => " two" ,
55
+ 3 => " three" ,
56
+ 4 => " four" ,
57
+ 5 => " five" ,
58
+ _ => " something else" ,
59
+ };
154
60
```
155
61
156
- Sometimes, it' s a nice pattern .
62
+ Sometimes, it’ s a nice way of converting things .
0 commit comments