11% Match
22
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
44possible options. Also, ` else ` conditions can get incredibly complicated, so
5- what' s the solution?
5+ what’ s the solution?
66
77Rust has a keyword, ` match ` , that allows you to replace complicated ` if ` /` else `
88groupings with something more powerful. Check it out:
99
10- ``` { rust}
10+ ``` rust
1111let x = 5 ;
1212
1313match x {
@@ -21,11 +21,14 @@ match x {
2121```
2222
2323` 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.
2728
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 `
2932enforces * exhaustiveness checking* . Do you see that last arm, the one with the
3033underscore (` _ ` )? If we remove that arm, Rust will give us an error:
3134
@@ -36,121 +39,24 @@ error: non-exhaustive patterns: `_` not covered
3639In other words, Rust is trying to tell us we forgot a value. Because ` x ` is an
3740integer, Rust knows that it can have a number of different values – for example,
3841` 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,
4043the arm with ` _ ` will, and since we have this catch-all arm, we now have an arm
4144for every possible value of ` x ` , and so our program will compile successfully.
4245
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-
13146` 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:
13748
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 ;
14751
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+ };
15460```
15561
156- Sometimes, it' s a nice pattern .
62+ Sometimes, it’ s a nice way of converting things .
0 commit comments