]> git.proxmox.com Git - rustc.git/blob - src/doc/book/src/ch18-01-all-the-places-for-patterns.md
New upstream version 1.43.0+dfsg1
[rustc.git] / src / doc / book / src / ch18-01-all-the-places-for-patterns.md
1 ## All the Places Patterns Can Be Used
2
3 Patterns pop up in a number of places in Rust, and you’ve been using them a lot
4 without realizing it! This section discusses all the places where patterns are
5 valid.
6
7 ### `match` Arms
8
9 As discussed in Chapter 6, we use patterns in the arms of `match` expressions.
10 Formally, `match` expressions are defined as the keyword `match`, a value to
11 match on, and one or more match arms that consist of a pattern and an
12 expression to run if the value matches that arm’s pattern, like this:
13
14 ```text
15 match VALUE {
16 PATTERN => EXPRESSION,
17 PATTERN => EXPRESSION,
18 PATTERN => EXPRESSION,
19 }
20 ```
21
22 One requirement for `match` expressions is that they need to be *exhaustive* in
23 the sense that all possibilities for the value in the `match` expression must
24 be accounted for. One way to ensure you’ve covered every possibility is to have
25 a catchall pattern for the last arm: for example, a variable name matching any
26 value can never fail and thus covers every remaining case.
27
28 A particular pattern `_` will match anything, but it never binds to a variable,
29 so it’s often used in the last match arm. The `_` pattern can be useful when
30 you want to ignore any value not specified, for example. We’ll cover the `_`
31 pattern in more detail in the [“Ignoring Values in a
32 Pattern”][ignoring-values-in-a-pattern]<!-- ignore --> section later in this
33 chapter.
34
35 ### Conditional `if let` Expressions
36
37 In Chapter 6 we discussed how to use `if let` expressions mainly as a shorter
38 way to write the equivalent of a `match` that only matches one case.
39 Optionally, `if let` can have a corresponding `else` containing code to run if
40 the pattern in the `if let` doesn’t match.
41
42 Listing 18-1 shows that it’s also possible to mix and match `if let`, `else
43 if`, and `else if let` expressions. Doing so gives us more flexibility than a
44 `match` expression in which we can express only one value to compare with the
45 patterns. Also, the conditions in a series of `if let`, `else if`, `else if
46 let` arms aren’t required to relate to each other.
47
48 The code in Listing 18-1 shows a series of checks for several conditions that
49 decide what the background color should be. For this example, we’ve created
50 variables with hardcoded values that a real program might receive from user
51 input.
52
53 <span class="filename">Filename: src/main.rs</span>
54
55 ```rust
56 {{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-01/src/main.rs}}
57 ```
58
59 <span class="caption">Listing 18-1: Mixing `if let`, `else if`, `else if let`,
60 and `else`</span>
61
62 If the user specifies a favorite color, that color is the background color. If
63 today is Tuesday, the background color is green. If the user specifies
64 their age as a string and we can parse it as a number successfully, the color
65 is either purple or orange depending on the value of the number. If none of
66 these conditions apply, the background color is blue.
67
68 This conditional structure lets us support complex requirements. With the
69 hardcoded values we have here, this example will print `Using purple as the
70 background color`.
71
72 You can see that `if let` can also introduce shadowed variables in the same way
73 that `match` arms can: the line `if let Ok(age) = age` introduces a new
74 shadowed `age` variable that contains the value inside the `Ok` variant. This
75 means we need to place the `if age > 30` condition within that block: we can’t
76 combine these two conditions into `if let Ok(age) = age && age > 30`. The
77 shadowed `age` we want to compare to 30 isn’t valid until the new scope starts
78 with the curly bracket.
79
80 The downside of using `if let` expressions is that the compiler doesn’t check
81 exhaustiveness, whereas with `match` expressions it does. If we omitted the
82 last `else` block and therefore missed handling some cases, the compiler would
83 not alert us to the possible logic bug.
84
85 ### `while let` Conditional Loops
86
87 Similar in construction to `if let`, the `while let` conditional loop allows a
88 `while` loop to run for as long as a pattern continues to match. The example in
89 Listing 18-2 shows a `while let` loop that uses a vector as a stack and prints
90 the values in the vector in the opposite order in which they were pushed.
91
92 ```rust
93 {{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-02/src/main.rs:here}}
94 ```
95
96 <span class="caption">Listing 18-2: Using a `while let` loop to print values
97 for as long as `stack.pop()` returns `Some`</span>
98
99 This example prints 3, 2, and then 1. The `pop` method takes the last element
100 out of the vector and returns `Some(value)`. If the vector is empty, `pop`
101 returns `None`. The `while` loop continues running the code in its block as
102 long as `pop` returns `Some`. When `pop` returns `None`, the loop stops. We can
103 use `while let` to pop every element off our stack.
104
105 ### `for` Loops
106
107 In Chapter 3, we mentioned that the `for` loop is the most common loop
108 construction in Rust code, but we haven’t yet discussed the pattern that `for`
109 takes. In a `for` loop, the pattern is the value that directly follows the
110 keyword `for`, so in `for x in y` the `x` is the pattern.
111
112 Listing 18-3 demonstrates how to use a pattern in a `for` loop to destructure,
113 or break apart, a tuple as part of the `for` loop.
114
115 ```rust
116 {{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-03/src/main.rs:here}}
117 ```
118
119 <span class="caption">Listing 18-3: Using a pattern in a `for` loop to
120 destructure a tuple</span>
121
122 The code in Listing 18-3 will print the following:
123
124 ```text
125 {{#include ../listings/ch18-patterns-and-matching/listing-18-03/output.txt}}
126 ```
127
128 We use the `enumerate` method to adapt an iterator to produce a value and that
129 value’s index in the iterator, placed into a tuple. The first call to
130 `enumerate` produces the tuple `(0, 'a')`. When this value is matched to the
131 pattern `(index, value)`, `index` will be `0` and `value` will be `'a'`,
132 printing the first line of the output.
133
134 ### `let` Statements
135
136 Prior to this chapter, we had only explicitly discussed using patterns with
137 `match` and `if let`, but in fact, we’ve used patterns in other places as well,
138 including in `let` statements. For example, consider this straightforward
139 variable assignment with `let`:
140
141 ```rust
142 let x = 5;
143 ```
144
145 Throughout this book, we’ve used `let` like this hundreds of times, and
146 although you might not have realized it, you were using patterns! More
147 formally, a `let` statement looks like this:
148
149 ```text
150 let PATTERN = EXPRESSION;
151 ```
152
153 In statements like `let x = 5;` with a variable name in the `PATTERN` slot, the
154 variable name is just a particularly simple form of a pattern. Rust compares
155 the expression against the pattern and assigns any names it finds. So in the
156 `let x = 5;` example, `x` is a pattern that means “bind what matches here to
157 the variable `x`.” Because the name `x` is the whole pattern, this pattern
158 effectively means “bind everything to the variable `x`, whatever the value is.”
159
160 To see the pattern matching aspect of `let` more clearly, consider Listing
161 18-4, which uses a pattern with `let` to destructure a tuple.
162
163 ```rust
164 {{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-04/src/main.rs:here}}
165 ```
166
167 <span class="caption">Listing 18-4: Using a pattern to destructure a tuple and
168 create three variables at once</span>
169
170 Here, we match a tuple against a pattern. Rust compares the value `(1, 2, 3)`
171 to the pattern `(x, y, z)` and sees that the value matches the pattern, so Rust
172 binds `1` to `x`, `2` to `y`, and `3` to `z`. You can think of this tuple
173 pattern as nesting three individual variable patterns inside it.
174
175 If the number of elements in the pattern doesn’t match the number of elements
176 in the tuple, the overall type won’t match and we’ll get a compiler error. For
177 example, Listing 18-5 shows an attempt to destructure a tuple with three
178 elements into two variables, which won’t work.
179
180 ```rust,ignore,does_not_compile
181 {{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-05/src/main.rs:here}}
182 ```
183
184 <span class="caption">Listing 18-5: Incorrectly constructing a pattern whose
185 variables don’t match the number of elements in the tuple</span>
186
187 Attempting to compile this code results in this type error:
188
189 ```text
190 {{#include ../listings/ch18-patterns-and-matching/listing-18-05/output.txt}}
191 ```
192
193 If we wanted to ignore one or more of the values in the tuple, we could use `_`
194 or `..`, as you’ll see in the [“Ignoring Values in a
195 Pattern”][ignoring-values-in-a-pattern]<!-- ignore --> section. If the problem
196 is that we have too many variables in the pattern, the solution is to make the
197 types match by removing variables so the number of variables equals the number
198 of elements in the tuple.
199
200 ### Function Parameters
201
202 Function parameters can also be patterns. The code in Listing 18-6, which
203 declares a function named `foo` that takes one parameter named `x` of type
204 `i32`, should by now look familiar.
205
206 ```rust
207 {{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-06/src/main.rs:here}}
208 ```
209
210 <span class="caption">Listing 18-6: A function signature uses patterns in the
211 parameters</span>
212
213 The `x` part is a pattern! As we did with `let`, we could match a tuple in a
214 function’s arguments to the pattern. Listing 18-7 splits the values in a tuple
215 as we pass it to a function.
216
217 <span class="filename">Filename: src/main.rs</span>
218
219 ```rust
220 {{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-07/src/main.rs}}
221 ```
222
223 <span class="caption">Listing 18-7: A function with parameters that destructure
224 a tuple</span>
225
226 This code prints `Current location: (3, 5)`. The values `&(3, 5)` match the
227 pattern `&(x, y)`, so `x` is the value `3` and `y` is the value `5`.
228
229 We can also use patterns in closure parameter lists in the same way as in
230 function parameter lists, because closures are similar to functions, as
231 discussed in Chapter 13.
232
233 At this point, you’ve seen several ways of using patterns, but patterns don’t
234 work the same in every place we can use them. In some places, the patterns must
235 be irrefutable; in other circumstances, they can be refutable. We’ll discuss
236 these two concepts next.
237
238 [ignoring-values-in-a-pattern]:
239 ch18-03-pattern-syntax.html#ignoring-values-in-a-pattern