]>
Commit | Line | Data |
---|---|---|
94b46f34 | 1 | ## Pattern Syntax |
83c7162d | 2 | |
94b46f34 XL |
3 | Throughout the book, you’ve seen examples of many kinds of patterns. In this |
4 | section, we gather all the syntax valid in patterns and discuss why you might | |
5 | want to use each one. | |
83c7162d XL |
6 | |
7 | ### Matching Literals | |
8 | ||
9 | As you saw in Chapter 6, you can match patterns against literals directly. The | |
10 | following code gives some examples: | |
11 | ||
12 | ```rust | |
13 | let x = 1; | |
14 | ||
15 | match x { | |
16 | 1 => println!("one"), | |
17 | 2 => println!("two"), | |
18 | 3 => println!("three"), | |
19 | _ => println!("anything"), | |
20 | } | |
21 | ``` | |
22 | ||
23 | This code prints `one` because the value in `x` is 1. This syntax is useful | |
24 | when you want your code to take an action if it gets a particular concrete | |
25 | value. | |
26 | ||
27 | ### Matching Named Variables | |
28 | ||
29 | Named variables are irrefutable patterns that match any value, and we’ve used | |
30 | them many times in the book. However, there is a complication when you use | |
31 | named variables in `match` expressions. Because `match` starts a new scope, | |
32 | variables declared as part of a pattern inside the `match` expression will | |
33 | shadow those with the same name outside the `match` construct, as is the case | |
34 | with all variables. In Listing 18-11, we declare a variable named `x` with the | |
35 | value `Some(5)` and a variable `y` with the value `10`. We then create a | |
36 | `match` expression on the value `x`. Look at the patterns in the match arms and | |
37 | `println!` at the end, and try to figure out what the code will print before | |
94b46f34 | 38 | running this code or reading further. |
83c7162d XL |
39 | |
40 | <span class="filename">Filename: src/main.rs</span> | |
41 | ||
42 | ```rust | |
43 | fn main() { | |
44 | let x = Some(5); | |
45 | let y = 10; | |
46 | ||
47 | match x { | |
48 | Some(50) => println!("Got 50"), | |
49 | Some(y) => println!("Matched, y = {:?}", y), | |
50 | _ => println!("Default case, x = {:?}", x), | |
51 | } | |
52 | ||
53 | println!("at the end: x = {:?}, y = {:?}", x, y); | |
54 | } | |
55 | ``` | |
56 | ||
57 | <span class="caption">Listing 18-11: A `match` expression with an arm that | |
58 | introduces a shadowed variable `y`</span> | |
59 | ||
60 | Let’s walk through what happens when the `match` expression runs. The pattern | |
61 | in the first match arm doesn’t match the defined value of `x`, so the code | |
62 | continues. | |
63 | ||
64 | The pattern in the second match arm introduces a new variable named `y` that | |
65 | will match any value inside a `Some` value. Because we’re in a new scope inside | |
66 | the `match` expression, this is a new `y` variable, not the `y` we declared at | |
67 | the beginning with the value 10. This new `y` binding will match any value | |
68 | inside a `Some`, which is what we have in `x`. Therefore, this new `y` binds to | |
69 | the inner value of the `Some` in `x`. That value is `5`, so the expression for | |
70 | that arm executes and prints `Matched, y = 5`. | |
71 | ||
72 | If `x` had been a `None` value instead of `Some(5)`, the patterns in the first | |
73 | two arms wouldn’t have matched, so the value would have matched to the | |
74 | underscore. We didn’t introduce the `x` variable in the pattern of the | |
75 | underscore arm, so the `x` in the expression is still the outer `x` that hasn’t | |
76 | been shadowed. In this hypothetical case, the `match` would print `Default | |
77 | case, x = None`. | |
78 | ||
79 | When the `match` expression is done, its scope ends, and so does the scope of | |
80 | the inner `y`. The last `println!` produces `at the end: x = Some(5), y = 10`. | |
81 | ||
82 | To create a `match` expression that compares the values of the outer `x` and | |
83 | `y`, rather than introducing a shadowed variable, we would need to use a match | |
84 | guard conditional instead. We’ll talk about match guards later in the “Extra | |
85 | Conditionals with Match Guards” section. | |
86 | ||
87 | ### Multiple Patterns | |
88 | ||
89 | In `match` expressions, you can match multiple patterns using the `|` syntax, | |
90 | which means *or*. For example, the following code matches the value of `x` | |
91 | against the match arms, the first of which has an *or* option, meaning if the | |
92 | value of `x` matches either of the values in that arm, that arm’s code will | |
93 | run: | |
94 | ||
95 | ```rust | |
96 | let x = 1; | |
97 | ||
98 | match x { | |
99 | 1 | 2 => println!("one or two"), | |
100 | 3 => println!("three"), | |
101 | _ => println!("anything"), | |
102 | } | |
103 | ``` | |
104 | ||
105 | This code prints `one or two`. | |
106 | ||
107 | ### Matching Ranges of Values with `...` | |
108 | ||
109 | The `...` syntax allows us to match to an inclusive range of values. In the | |
110 | following code, when a pattern matches any of the values within the range, that | |
111 | arm will execute: | |
112 | ||
113 | ```rust | |
114 | let x = 5; | |
115 | ||
116 | match x { | |
117 | 1 ... 5 => println!("one through five"), | |
118 | _ => println!("something else"), | |
119 | } | |
120 | ``` | |
121 | ||
122 | If `x` is 1, 2, 3, 4, or 5, the first arm will match. This syntax is more | |
123 | convenient than using the `|` operator to express the same idea; instead of `1 | |
124 | ... 5`, we would have to specify `1 | 2 | 3 | 4 | 5` if we used `|`. Specifying | |
125 | a range is much shorter, especially if we want to match, say, any number | |
126 | between 1 and 1,000! | |
127 | ||
128 | Ranges are only allowed with numeric values or `char` values, because the | |
129 | compiler checks that the range isn’t empty at compile time. The only types for | |
130 | which Rust can tell if a range is empty or not are `char` and numeric values. | |
131 | ||
132 | Here is an example using ranges of `char` values: | |
133 | ||
134 | ```rust | |
135 | let x = 'c'; | |
136 | ||
137 | match x { | |
138 | 'a' ... 'j' => println!("early ASCII letter"), | |
139 | 'k' ... 'z' => println!("late ASCII letter"), | |
140 | _ => println!("something else"), | |
141 | } | |
142 | ``` | |
143 | ||
144 | Rust can tell that `c` is within the first pattern’s range and prints `early | |
145 | ASCII letter`. | |
146 | ||
147 | ### Destructuring to Break Apart Values | |
148 | ||
149 | We can also use patterns to destructure structs, enums, tuples, and references | |
150 | to use different parts of these values. Let’s walk through each value. | |
151 | ||
152 | #### Destructuring Structs | |
153 | ||
154 | Listing 18-12 shows a `Point` struct with two fields, `x` and `y`, that we can | |
94b46f34 | 155 | break apart using a pattern with a `let` statement. |
83c7162d XL |
156 | |
157 | <span class="filename">Filename: src/main.rs</span> | |
158 | ||
159 | ```rust | |
160 | struct Point { | |
161 | x: i32, | |
162 | y: i32, | |
163 | } | |
164 | ||
165 | fn main() { | |
166 | let p = Point { x: 0, y: 7 }; | |
167 | ||
168 | let Point { x: a, y: b } = p; | |
169 | assert_eq!(0, a); | |
170 | assert_eq!(7, b); | |
171 | } | |
172 | ``` | |
173 | ||
174 | <span class="caption">Listing 18-12: Destructuring a struct’s fields into | |
175 | separate variables</span> | |
176 | ||
177 | This code creates the variables `a` and `b` that match the values of the `x` | |
178 | and `y` fields of the `p` variable. This example shows that the names of the | |
179 | variables in the pattern don’t have to match the field names of the struct. But | |
180 | it’s common to want the variable names to match the field names to make it | |
181 | easier to remember which variables came from which fields. | |
182 | ||
183 | Because having variable names match the fields is common and because writing | |
184 | `let Point { x: x, y: y } = p;` contains a lot of duplication, there is a | |
185 | shorthand for patterns that match struct fields: you only need to list the name | |
186 | of the struct field, and the variables created from the pattern will have the | |
187 | same names. Listing 18-13 shows code that behaves in the same way as the code | |
188 | in Listing 18-12, but the variables created in the `let` pattern are `x` and | |
94b46f34 | 189 | `y` instead of `a` and `b`. |
83c7162d XL |
190 | |
191 | <span class="filename">Filename: src/main.rs</span> | |
192 | ||
193 | ```rust | |
194 | struct Point { | |
195 | x: i32, | |
196 | y: i32, | |
197 | } | |
198 | ||
199 | fn main() { | |
200 | let p = Point { x: 0, y: 7 }; | |
201 | ||
202 | let Point { x, y } = p; | |
203 | assert_eq!(0, x); | |
204 | assert_eq!(7, y); | |
205 | } | |
206 | ``` | |
207 | ||
208 | <span class="caption">Listing 18-13: Destructuring struct fields using struct | |
209 | field shorthand</span> | |
210 | ||
211 | This code creates the variables `x` and `y` that match the `x` and `y` fields | |
212 | of the `p` variable. The outcome is that the variables `x` and `y` contain the | |
213 | values from the `p` struct. | |
214 | ||
215 | We can also destructure with literal values as part of the struct pattern | |
216 | rather than creating variables for all the fields. Doing so allows us to test | |
217 | some of the fields for particular values while creating variables to | |
218 | destructure the other fields. | |
219 | ||
220 | Listing 18-14 shows a `match` expression that separates `Point` values into | |
221 | three cases: points that lie directly on the `x` axis (which is true when `y = | |
94b46f34 | 222 | 0`), on the `y` axis (`x = 0`), or neither. |
83c7162d XL |
223 | |
224 | <span class="filename">Filename: src/main.rs</span> | |
225 | ||
226 | ```rust | |
227 | # struct Point { | |
228 | # x: i32, | |
229 | # y: i32, | |
230 | # } | |
231 | # | |
232 | fn main() { | |
233 | let p = Point { x: 0, y: 7 }; | |
234 | ||
235 | match p { | |
236 | Point { x, y: 0 } => println!("On the x axis at {}", x), | |
237 | Point { x: 0, y } => println!("On the y axis at {}", y), | |
238 | Point { x, y } => println!("On neither axis: ({}, {})", x, y), | |
239 | } | |
240 | } | |
241 | ``` | |
242 | ||
243 | <span class="caption">Listing 18-14: Destructuring and matching literal values | |
244 | in one pattern</span> | |
245 | ||
246 | The first arm will match any point that lies on the `x` axis by specifying that | |
247 | the `y` field matches if its value matches the literal `0`. The pattern still | |
248 | creates an `x` variable that we can use in the code for this arm. | |
249 | ||
250 | Similarly, the second arm matches any point on the `y` axis by specifying that | |
251 | the `x` field matches if its value is `0` and creates a variable `y` for the | |
252 | value of the `y` field. The third arm doesn’t specify any literals, so it | |
253 | matches any other `Point` and creates variables for both the `x` and `y` fields. | |
254 | ||
255 | In this example, the value `p` matches the second arm by virtue of `x` | |
256 | containing a 0, so this code will print `On the y axis at 7`. | |
257 | ||
258 | #### Destructuring Enums | |
259 | ||
260 | We’ve destructured enums earlier in this book, for example, when we | |
261 | destructured `Option<i32>` in Listing 6-5 in Chapter 6. One detail we haven’t | |
262 | mentioned explicitly is that the pattern to destructure an enum should | |
263 | correspond to the way the data stored within the enum is defined. As an | |
264 | example, in Listing 18-15 we use the `Message` enum from Listing 6-2 and write | |
94b46f34 | 265 | a `match` with patterns that will destructure each inner value. |
83c7162d XL |
266 | |
267 | <span class="filename">Filename: src/main.rs</span> | |
268 | ||
269 | ```rust | |
270 | enum Message { | |
271 | Quit, | |
272 | Move { x: i32, y: i32 }, | |
273 | Write(String), | |
274 | ChangeColor(i32, i32, i32), | |
275 | } | |
276 | ||
277 | fn main() { | |
278 | let msg = Message::ChangeColor(0, 160, 255); | |
279 | ||
280 | match msg { | |
281 | Message::Quit => { | |
282 | println!("The Quit variant has no data to destructure.") | |
283 | }, | |
284 | Message::Move { x, y } => { | |
285 | println!( | |
286 | "Move in the x direction {} and in the y direction {}", | |
287 | x, | |
288 | y | |
289 | ); | |
290 | } | |
291 | Message::Write(text) => println!("Text message: {}", text), | |
292 | Message::ChangeColor(r, g, b) => { | |
293 | println!( | |
294 | "Change the color to red {}, green {}, and blue {}", | |
295 | r, | |
296 | g, | |
297 | b | |
298 | ) | |
299 | } | |
300 | } | |
301 | } | |
302 | ``` | |
303 | ||
304 | <span class="caption">Listing 18-15: Destructuring enum variants that hold | |
305 | different kinds of values</span> | |
306 | ||
307 | This code will print `Change the color to red 0, green 160, and blue 255`. Try | |
308 | changing the value of `msg` to see the code from the other arms run. | |
309 | ||
310 | For enum variants without any data, like `Message::Quit`, we can’t destructure | |
311 | the value any further. We can only match on the literal `Message::Quit` value, | |
312 | and no variables are in that pattern. | |
313 | ||
314 | For struct-like enum variants, such as `Message::Move`, we can use a pattern | |
315 | similar to the pattern we specify to match structs. After the variant name, we | |
316 | place curly brackets and then list the fields with variables so we break apart | |
317 | the pieces to use in the code for this arm. Here we use the shorthand form as | |
318 | we did in Listing 18-13. | |
319 | ||
320 | For tuple-like enum variants, like `Message::Write` that holds a tuple with one | |
321 | element and `Message::ChangeColor` that holds a tuple with three elements, the | |
322 | pattern is similar to the pattern we specify to match tuples. The number of | |
323 | variables in the pattern must match the number of elements in the variant we’re | |
324 | matching. | |
325 | ||
94b46f34 XL |
326 | #### Destructuring Nested Structs & Enums |
327 | ||
328 | Up until now, all of our examples have been matching structures that were one | |
329 | level deep. Matching can work on nested structures too! | |
330 | ||
331 | We can refactor the example above to support both RGB and HSV colors: | |
332 | ||
333 | ```rust | |
334 | enum Color { | |
335 | Rgb(i32, i32, i32), | |
336 | Hsv(i32, i32, i32) | |
337 | } | |
338 | ||
339 | enum Message { | |
340 | Quit, | |
341 | Move { x: i32, y: i32 }, | |
342 | Write(String), | |
343 | ChangeColor(Color), | |
344 | } | |
345 | ||
346 | fn main() { | |
347 | let msg = Message::ChangeColor(Color::Hsv(0, 160, 255)); | |
348 | ||
349 | match msg { | |
350 | Message::ChangeColor(Color::Rgb(r, g, b)) => { | |
351 | println!( | |
352 | "Change the color to red {}, green {}, and blue {}", | |
353 | r, | |
354 | g, | |
355 | b | |
356 | ) | |
357 | }, | |
358 | Message::ChangeColor(Color::Hsv(h, s, v)) => { | |
359 | println!( | |
360 | "Change the color to hue {}, saturation {}, and value {}", | |
361 | h, | |
362 | s, | |
363 | v | |
364 | ) | |
365 | } | |
366 | _ => () | |
367 | } | |
368 | } | |
369 | ``` | |
370 | ||
83c7162d XL |
371 | #### Destructuring References |
372 | ||
373 | When the value we’re matching to our pattern contains a reference, we need to | |
374 | destructure the reference from the value, which we can do by specifying a `&` | |
375 | in the pattern. Doing so lets us get a variable holding the value that the | |
376 | reference points to rather than getting a variable that holds the reference. | |
377 | This technique is especially useful in closures where we have iterators that | |
378 | iterate over references, but we want to use the values in the closure rather | |
379 | than the references. | |
380 | ||
381 | The example in Listing 18-16 iterates over references to `Point` instances in a | |
94b46f34 XL |
382 | vector, destructuring the reference and the struct so we can perform |
383 | calculations on the `x` and `y` values easily. | |
83c7162d XL |
384 | |
385 | ```rust | |
386 | # struct Point { | |
387 | # x: i32, | |
388 | # y: i32, | |
389 | # } | |
390 | # | |
391 | let points = vec![ | |
392 | Point { x: 0, y: 0 }, | |
393 | Point { x: 1, y: 5 }, | |
394 | Point { x: 10, y: -3 }, | |
395 | ]; | |
396 | ||
397 | let sum_of_squares: i32 = points | |
398 | .iter() | |
399 | .map(|&Point { x, y }| x * x + y * y) | |
400 | .sum(); | |
401 | ``` | |
402 | ||
403 | <span class="caption">Listing 18-16: Destructuring a reference to a struct into | |
404 | the struct field values</span> | |
405 | ||
406 | This code gives us the variable `sum_of_squares` holding the value 135, which | |
407 | is the result of squaring the `x` value and the `y` value, adding those | |
408 | together, and then adding the result for each `Point` in the `points` vector to | |
409 | get one number. | |
410 | ||
94b46f34 | 411 | If we had not included the `&` in `&Point { x, y }`, we’d get a type mismatch |
83c7162d XL |
412 | error, because `iter` would then iterate over references to the items in the |
413 | vector rather than the actual values. The error would look like this: | |
414 | ||
415 | ```text | |
416 | error[E0308]: mismatched types | |
417 | --> | |
418 | | | |
419 | 14 | .map(|Point { x, y }| x * x + y * y) | |
420 | | ^^^^^^^^^^^^ expected &Point, found struct `Point` | |
421 | | | |
422 | = note: expected type `&Point` | |
423 | found type `Point` | |
424 | ``` | |
425 | ||
426 | This error indicates that Rust was expecting our closure to match `&Point`, but | |
427 | we tried to match directly to a `Point` value, not a reference to a `Point`. | |
428 | ||
429 | #### Destructuring Structs and Tuples | |
430 | ||
431 | We can mix, match, and nest destructuring patterns in even more complex ways. | |
432 | The following example shows a complicated destructure where we nest structs and | |
94b46f34 | 433 | tuples inside a tuple and destructure all the primitive values out: |
83c7162d XL |
434 | |
435 | ```rust | |
436 | # struct Point { | |
437 | # x: i32, | |
438 | # y: i32, | |
439 | # } | |
440 | # | |
441 | let ((feet, inches), Point {x, y}) = ((3, 10), Point { x: 3, y: -10 }); | |
442 | ``` | |
443 | ||
444 | This code lets us break complex types into their component parts so we can use | |
445 | the values we’re interested in separately. | |
446 | ||
447 | Destructuring with patterns is a convenient way to use pieces of values, such | |
448 | as the value from each field in a struct, separately from each other. | |
449 | ||
450 | ### Ignoring Values in a Pattern | |
451 | ||
452 | You’ve seen that it’s sometimes useful to ignore values in a pattern, such as | |
453 | in the last arm of a `match`, to get a catchall that doesn’t actually do | |
454 | anything but does account for all remaining possible values. There are a few | |
455 | ways to ignore entire values or parts of values in a pattern: using the `_` | |
456 | pattern (which you’ve seen), using the `_` pattern within another pattern, | |
457 | using a name that starts with an underscore, or using `..` to ignore remaining | |
458 | parts of a value. Let’s explore how and why to use each of these patterns. | |
459 | ||
460 | #### Ignoring an Entire Value with `_` | |
461 | ||
94b46f34 | 462 | We’ve used the underscore (`_`) as a wildcard pattern that will match any value |
83c7162d XL |
463 | but not bind to the value. Although the underscore `_` pattern is especially |
464 | useful as the last arm in a `match` expression, we can use it in any pattern, | |
94b46f34 | 465 | including function parameters, as shown in Listing 18-17. |
83c7162d XL |
466 | |
467 | <span class="filename">Filename: src/main.rs</span> | |
468 | ||
469 | ```rust | |
470 | fn foo(_: i32, y: i32) { | |
471 | println!("This code only uses the y parameter: {}", y); | |
472 | } | |
473 | ||
474 | fn main() { | |
475 | foo(3, 4); | |
476 | } | |
477 | ``` | |
478 | ||
479 | <span class="caption">Listing 18-17: Using `_` in a function signature</span> | |
480 | ||
481 | This code will completely ignore the value passed as the first argument, `3`, | |
482 | and will print `This code only uses the y parameter: 4`. | |
483 | ||
484 | In most cases when you no longer need a particular function parameter, you | |
485 | would change the signature so it doesn’t include the unused parameter. Ignoring | |
94b46f34 | 486 | a function parameter can be especially useful in some cases, for example, when |
83c7162d XL |
487 | implementing a trait when you need a certain type signature but the function |
488 | body in your implementation doesn’t need one of the parameters. The compiler | |
489 | will then not warn about unused function parameters, as it would if you used a | |
490 | name instead. | |
491 | ||
492 | #### Ignoring Parts of a Value with a Nested `_` | |
493 | ||
94b46f34 XL |
494 | We can also use `_` inside another pattern to ignore just part of a value, for |
495 | example, when we want to test for only part of a value but have no use for the | |
83c7162d XL |
496 | other parts in the corresponding code we want to run. Listing 18-18 shows code |
497 | responsible for managing a setting’s value. The business requirements are that | |
498 | the user should not be allowed to overwrite an existing customization of a | |
499 | setting but can unset the setting and can give the setting a value if it is | |
500 | currently unset. | |
501 | ||
502 | ```rust | |
503 | let mut setting_value = Some(5); | |
504 | let new_setting_value = Some(10); | |
505 | ||
506 | match (setting_value, new_setting_value) { | |
507 | (Some(_), Some(_)) => { | |
508 | println!("Can't overwrite an existing customized value"); | |
509 | } | |
510 | _ => { | |
511 | setting_value = new_setting_value; | |
512 | } | |
513 | } | |
514 | ||
515 | println!("setting is {:?}", setting_value); | |
516 | ``` | |
517 | ||
518 | <span class="caption">Listing 18-18: Using an underscore within patterns that | |
519 | match `Some` variants when we don’t need to use the value inside the | |
520 | `Some`</span> | |
521 | ||
522 | This code will print `Can't overwrite an existing customized value` and then | |
523 | `setting is Some(5)`. In the first match arm, we don’t need to match on or use | |
524 | the values inside either `Some` variant, but we do need to test for the case | |
525 | when `setting_value` and `new_setting_value` are the `Some` variant. In that | |
526 | case, we print why we’re not changing `setting_value`, and it doesn’t get | |
527 | changed. | |
528 | ||
529 | In all other cases (if either `setting_value` or `new_setting_value` are | |
530 | `None`) expressed by the `_` pattern in the second arm, we want to allow | |
531 | `new_setting_value` to become `setting_value`. | |
532 | ||
533 | We can also use underscores in multiple places within one pattern to ignore | |
534 | particular values. Listing 18-19 shows an example of ignoring the second and | |
94b46f34 | 535 | fourth values in a tuple of five items. |
83c7162d XL |
536 | |
537 | ```rust | |
538 | let numbers = (2, 4, 8, 16, 32); | |
539 | ||
540 | match numbers { | |
541 | (first, _, third, _, fifth) => { | |
542 | println!("Some numbers: {}, {}, {}", first, third, fifth) | |
543 | }, | |
544 | } | |
545 | ``` | |
546 | ||
547 | <span class="caption">Listing 18-19: Ignoring multiple parts of a tuple</span> | |
548 | ||
549 | This code will print `Some numbers: 2, 8, 32`, and the values 4 and 16 will be | |
550 | ignored. | |
551 | ||
94b46f34 | 552 | #### Ignoring an Unused Variable by Starting Its Name with `_` |
83c7162d XL |
553 | |
554 | If you create a variable but don’t use it anywhere, Rust will usually issue a | |
555 | warning because that could be a bug. But sometimes it’s useful to create a | |
556 | variable you won’t use yet, such as when you’re prototyping or just starting a | |
557 | project. In this situation, you can tell Rust not to warn you about the unused | |
558 | variable by starting the name of the variable with an underscore. In Listing | |
559 | 18-20, we create two unused variables, but when we run this code, we should | |
560 | only get a warning about one of them. | |
561 | ||
562 | <span class="filename">Filename: src/main.rs</span> | |
563 | ||
564 | ```rust | |
565 | fn main() { | |
566 | let _x = 5; | |
567 | let y = 10; | |
568 | } | |
569 | ``` | |
570 | ||
571 | <span class="caption">Listing 18-20: Starting a variable name with an | |
572 | underscore to avoid getting unused variable warnings</span> | |
573 | ||
574 | Here we get a warning about not using the variable `y`, but we don’t get a | |
575 | warning about not using the variable preceded by the underscore. | |
576 | ||
577 | Note that there is a subtle difference between using only `_` and using a name | |
578 | that starts with an underscore. The syntax `_x` still binds the value to the | |
579 | variable, whereas `_` doesn’t bind at all. To show a case where this | |
94b46f34 | 580 | distinction matters, Listing 18-21 will provide us with an error. |
83c7162d XL |
581 | |
582 | ```rust,ignore | |
583 | let s = Some(String::from("Hello!")); | |
584 | ||
585 | if let Some(_s) = s { | |
586 | println!("found a string"); | |
587 | } | |
588 | ||
589 | println!("{:?}", s); | |
590 | ``` | |
591 | ||
592 | <span class="caption">Listing 18-21: An unused variable starting with an | |
593 | underscore still binds the value, which might take ownership of the value</span> | |
594 | ||
595 | We’ll receive an error because the `s` value will still be moved into `_s`, | |
596 | which prevents us from using `s` again. However, using the underscore by itself | |
597 | doesn’t ever bind to the value. Listing 18-22 will compile without any errors | |
94b46f34 | 598 | because `s` doesn’t get moved into `_`. |
83c7162d XL |
599 | |
600 | ```rust | |
601 | let s = Some(String::from("Hello!")); | |
602 | ||
603 | if let Some(_) = s { | |
604 | println!("found a string"); | |
605 | } | |
606 | ||
607 | println!("{:?}", s); | |
608 | ``` | |
609 | ||
610 | <span class="caption">Listing 18-22: Using an underscore does not bind the | |
611 | value</span> | |
612 | ||
613 | This code works just fine because we never bind `s` to anything; it isn’t moved. | |
614 | ||
615 | #### Ignoring Remaining Parts of a Value with `..` | |
616 | ||
617 | With values that have many parts, we can use the `..` syntax to use only a few | |
94b46f34 | 618 | parts and ignore the rest, avoiding the need to list underscores for each |
83c7162d XL |
619 | ignored value. The `..` pattern ignores any parts of a value that we haven’t |
620 | explicitly matched in the rest of the pattern. In Listing 18-23, we have a | |
621 | `Point` struct that holds a coordinate in three-dimensional space. In the | |
622 | `match` expression, we want to operate only on the `x` coordinate and ignore | |
94b46f34 | 623 | the values in the `y` and `z` fields. |
83c7162d XL |
624 | |
625 | ```rust | |
626 | struct Point { | |
627 | x: i32, | |
628 | y: i32, | |
629 | z: i32, | |
630 | } | |
631 | ||
632 | let origin = Point { x: 0, y: 0, z: 0 }; | |
633 | ||
634 | match origin { | |
635 | Point { x, .. } => println!("x is {}", x), | |
636 | } | |
637 | ``` | |
638 | ||
639 | <span class="caption">Listing 18-23: Ignoring all fields of a `Point` except | |
640 | for `x` by using `..`</span> | |
641 | ||
94b46f34 | 642 | We list the `x` value and then just include the `..` pattern. This is quicker |
83c7162d XL |
643 | than having to list `y: _` and `z: _`, particularly when we’re working with |
644 | structs that have lots of fields in situations where only one or two fields are | |
645 | relevant. | |
646 | ||
647 | The syntax `..` will expand to as many values as it needs to be. Listing 18-24 | |
94b46f34 | 648 | shows how to use `..` with a tuple. |
83c7162d XL |
649 | |
650 | <span class="filename">Filename: src/main.rs</span> | |
651 | ||
652 | ```rust | |
653 | fn main() { | |
654 | let numbers = (2, 4, 8, 16, 32); | |
655 | ||
656 | match numbers { | |
657 | (first, .., last) => { | |
658 | println!("Some numbers: {}, {}", first, last); | |
659 | }, | |
660 | } | |
661 | } | |
662 | ``` | |
663 | ||
664 | <span class="caption">Listing 18-24: Matching only the first and last values in | |
665 | a tuple and ignoring all other values</span> | |
666 | ||
667 | In this code, the first and last value are matched with `first` and `last`. The | |
668 | `..` will match and ignore everything in the middle. | |
669 | ||
670 | However, using `..` must be unambiguous. If it is unclear which values are | |
94b46f34 XL |
671 | intended for matching and which should be ignored, Rust will give us an error. |
672 | Listing 18-25 shows an example of using `..` ambiguously, so it will not | |
673 | compile. | |
83c7162d XL |
674 | |
675 | <span class="filename">Filename: src/main.rs</span> | |
676 | ||
677 | ```rust,ignore | |
678 | fn main() { | |
679 | let numbers = (2, 4, 8, 16, 32); | |
680 | ||
681 | match numbers { | |
682 | (.., second, ..) => { | |
683 | println!("Some numbers: {}", second) | |
684 | }, | |
685 | } | |
686 | } | |
687 | ``` | |
688 | ||
689 | <span class="caption">Listing 18-25: An attempt to use `..` in an ambiguous | |
690 | way</span> | |
691 | ||
692 | When we compile this example, we get this error: | |
693 | ||
694 | ```text | |
695 | error: `..` can only be used once per tuple or tuple struct pattern | |
696 | --> src/main.rs:5:22 | |
697 | | | |
698 | 5 | (.., second, ..) => { | |
699 | | ^^ | |
700 | ``` | |
701 | ||
702 | It’s impossible for Rust to determine how many values in the tuple to ignore | |
94b46f34 | 703 | before matching a value with `second` and then how many further values to |
83c7162d XL |
704 | ignore thereafter. This code could mean that we want to ignore `2`, bind |
705 | `second` to `4`, and then ignore `8`, `16`, and `32`; or that we want to ignore | |
706 | `2` and `4`, bind `second` to `8`, and then ignore `16` and `32`; and so forth. | |
707 | The variable name `second` doesn’t mean anything special to Rust, so we get a | |
708 | compiler error because using `..` in two places like this is ambiguous. | |
709 | ||
94b46f34 | 710 | ### Creating References in Patterns with `ref` and `ref mut` |
83c7162d XL |
711 | |
712 | Let’s look at using `ref` to make references so ownership of the values isn’t | |
713 | moved to variables in the pattern. Usually, when you match against a pattern, | |
714 | the variables introduced by the pattern are bound to a value. Rust’s ownership | |
715 | rules mean the value will be moved into the `match` or wherever you’re using | |
716 | the pattern. Listing 18-26 shows an example of a `match` that has a pattern | |
717 | with a variable and then usage of the entire value in the `println!` statement | |
718 | later, after the `match`. This code will fail to compile because ownership of | |
719 | part of the `robot_name` value is transferred to the `name` variable in the | |
94b46f34 | 720 | pattern of the first `match` arm. |
83c7162d XL |
721 | |
722 | ```rust,ignore | |
723 | let robot_name = Some(String::from("Bors")); | |
724 | ||
725 | match robot_name { | |
726 | Some(name) => println!("Found a name: {}", name), | |
727 | None => (), | |
728 | } | |
729 | ||
730 | println!("robot_name is: {:?}", robot_name); | |
731 | ``` | |
732 | ||
733 | <span class="caption">Listing 18-26: Creating a variable in a `match` arm | |
734 | pattern takes ownership of the value</span> | |
735 | ||
736 | Because ownership of part of `robot_name` has been moved to `name`, we can no | |
737 | longer use `robot_name` in the `println!` after the `match` because | |
738 | `robot_name` no longer has ownership. | |
739 | ||
740 | To fix this code, we want to make the `Some(name)` pattern *borrow* that part | |
741 | of `robot_name` rather than taking ownership. You’ve already seen that, outside | |
742 | of patterns, the way to borrow a value is to create a reference using `&`, so | |
743 | you might think the solution is changing `Some(name)` to `Some(&name)`. | |
744 | ||
745 | However, as you saw in the “Destructuring to Break Apart Values” section, the | |
746 | syntax `&` in patterns does not *create* a reference but *matches* an existing | |
747 | reference in the value. Because `&` already has that meaning in patterns, we | |
748 | can’t use `&` to create a reference in a pattern. | |
749 | ||
750 | Instead, to create a reference in a pattern, we use the `ref` keyword before | |
94b46f34 | 751 | the new variable, as shown in Listing 18-27. |
83c7162d XL |
752 | |
753 | ```rust | |
754 | let robot_name = Some(String::from("Bors")); | |
755 | ||
756 | match robot_name { | |
757 | Some(ref name) => println!("Found a name: {}", name), | |
758 | None => (), | |
759 | } | |
760 | ||
761 | println!("robot_name is: {:?}", robot_name); | |
762 | ``` | |
763 | ||
764 | <span class="caption">Listing 18-27: Creating a reference so a pattern variable | |
765 | does not take ownership of a value</span> | |
766 | ||
767 | This example will compile because the value in the `Some` variant in | |
768 | `robot_name` is not moved into the `match`; the `match` only took a reference | |
769 | to the data in `robot_name` rather than moving it. | |
770 | ||
771 | To create a mutable reference so we’re able to mutate a value matched in a | |
772 | pattern, we use `ref mut` instead of `&mut`. The reason is, again, that in | |
773 | patterns, the latter is for matching existing mutable references, not creating | |
774 | new ones. Listing 18-28 shows an example of a pattern creating a mutable | |
94b46f34 | 775 | reference. |
83c7162d XL |
776 | |
777 | ```rust | |
778 | let mut robot_name = Some(String::from("Bors")); | |
779 | ||
780 | match robot_name { | |
781 | Some(ref mut name) => *name = String::from("Another name"), | |
782 | None => (), | |
783 | } | |
784 | ||
785 | println!("robot_name is: {:?}", robot_name); | |
786 | ``` | |
787 | ||
788 | <span class="caption">Listing 18-28: Creating a mutable reference to a value as | |
789 | part of a pattern using `ref mut`</span> | |
790 | ||
791 | This example will compile and print `robot_name is: Some("Another name")`. | |
792 | Because `name` is a mutable reference, we need to dereference within the match | |
793 | arm code using the `*` operator to mutate the value. | |
794 | ||
795 | ### Extra Conditionals with Match Guards | |
796 | ||
797 | A *match guard* is an additional `if` condition specified after the pattern in | |
798 | a `match` arm that must also match, along with the pattern matching, for that | |
799 | arm to be chosen. Match guards are useful for expressing more complex ideas | |
800 | than a pattern alone allows. | |
801 | ||
802 | The condition can use variables created in the pattern. Listing 18-29 shows a | |
803 | `match` where the first arm has the pattern `Some(x)` and also has a match | |
94b46f34 | 804 | guard of `if x < 5`. |
83c7162d XL |
805 | |
806 | ```rust | |
807 | let num = Some(4); | |
808 | ||
809 | match num { | |
810 | Some(x) if x < 5 => println!("less than five: {}", x), | |
811 | Some(x) => println!("{}", x), | |
812 | None => (), | |
813 | } | |
814 | ``` | |
815 | ||
816 | <span class="caption">Listing 18-29: Adding a match guard to a pattern</span> | |
817 | ||
818 | This example will print `less than five: 4`. When `num` is compared to the | |
819 | pattern in the first arm, it matches, because `Some(4)` matches `Some(x)`. Then | |
820 | the match guard checks whether the value in `x` is less than `5`, and because | |
821 | it is, the first arm is selected. | |
822 | ||
823 | If `num` had been `Some(10)` instead, the match guard in the first arm would | |
824 | have been false because 10 is not less than 5. Rust would then go to the second | |
825 | arm, which would match because the second arm doesn’t have a match guard and | |
826 | therefore matches any `Some` variant. | |
827 | ||
828 | There is no way to express the `if x < 5` condition within a pattern, so the | |
829 | match guard gives us the ability to express this logic. | |
830 | ||
831 | In Listing 18-11, we mentioned that we could use match guards to solve our | |
94b46f34 | 832 | pattern-shadowing problem. Recall that a new variable was created inside the |
83c7162d XL |
833 | pattern in the `match` expression instead of using the variable outside the |
834 | `match`. That new variable meant we couldn’t test against the value of the | |
835 | outer variable. Listing 18-30 shows how we can use a match guard to fix this | |
94b46f34 | 836 | problem. |
83c7162d XL |
837 | |
838 | <span class="filename">Filename: src/main.rs</span> | |
839 | ||
840 | ```rust | |
841 | fn main() { | |
842 | let x = Some(5); | |
843 | let y = 10; | |
844 | ||
845 | match x { | |
846 | Some(50) => println!("Got 50"), | |
847 | Some(n) if n == y => println!("Matched, n = {:?}", n), | |
848 | _ => println!("Default case, x = {:?}", x), | |
849 | } | |
850 | ||
851 | println!("at the end: x = {:?}, y = {:?}", x, y); | |
852 | } | |
853 | ``` | |
854 | ||
855 | <span class="caption">Listing 18-30: Using a match guard to test for equality | |
856 | with an outer variable</span> | |
857 | ||
858 | This code will now print `Default case, x = Some(5)`. The pattern in the second | |
859 | match arm doesn’t introduce a new variable `y` that would shadow the outer `y`, | |
860 | meaning we can use the outer `y` in the match guard. Instead of specifying the | |
861 | pattern as `Some(y)`, which would have shadowed the outer `y`, we specify | |
862 | `Some(n)`. This creates a new variable `n` that doesn’t shadow anything because | |
863 | there is no `n` variable outside the `match`. | |
864 | ||
865 | The match guard `if n == y` is not a pattern and therefore doesn’t introduce | |
866 | new variables. This `y` *is* the outer `y` rather than a new shadowed `y`, and | |
867 | we can look for a value that has the same value as the outer `y` by comparing | |
868 | `n` to `y`. | |
869 | ||
870 | You can also use the *or* operator `|` in a match guard to specify multiple | |
871 | patterns; the match guard condition will apply to all the patterns. Listing | |
872 | 18-31 shows the precedence of combining a match guard with a pattern that uses | |
873 | `|`. The important part of this example is that the `if y` match guard applies | |
874 | to `4`, `5`, *and* `6`, even though it might look like `if y` only applies to | |
94b46f34 | 875 | `6`. |
83c7162d XL |
876 | |
877 | ```rust | |
878 | let x = 4; | |
879 | let y = false; | |
880 | ||
881 | match x { | |
882 | 4 | 5 | 6 if y => println!("yes"), | |
883 | _ => println!("no"), | |
884 | } | |
885 | ``` | |
886 | ||
887 | <span class="caption">Listing 18-31: Combining multiple patterns with a match | |
888 | guard</span> | |
889 | ||
890 | The match condition states that the arm only matches if the value of `x` is | |
891 | equal to `4`, `5`, or `6` *and* if `y` is `true`. When this code runs, the | |
892 | pattern of the first arm matches because `x` is `4`, but the match guard `if y` | |
893 | is false, so the first arm is not chosen. The code moves on to the second arm, | |
894 | which does match, and this program prints `no`. The reason is that the `if` | |
895 | condition applies to the whole pattern `4 | 5 | 6`, not only to the last value | |
896 | `6`. In other words, the precedence of a match guard in relation to a pattern | |
897 | behaves like this: | |
898 | ||
899 | ```text | |
900 | (4 | 5 | 6) if y => ... | |
901 | ``` | |
902 | ||
903 | rather than this: | |
904 | ||
905 | ```text | |
906 | 4 | 5 | (6 if y) => ... | |
907 | ``` | |
908 | ||
909 | After running the code, the precedence behavior is evident: if the match guard | |
94b46f34 | 910 | were applied only to the final value in the list of values specified using the |
83c7162d XL |
911 | `|` operator, the arm would have matched and the program would have printed |
912 | `yes`. | |
913 | ||
914 | ### `@` Bindings | |
915 | ||
94b46f34 XL |
916 | The *at* operator (`@`) lets us create a variable that holds a value at the |
917 | same time we’re testing that value to see whether it matches a pattern. Listing | |
83c7162d XL |
918 | 18-32 shows an example where we want to test that a `Message::Hello` `id` field |
919 | is within the range `3...7`. But we also want to bind the value to the variable | |
920 | `id_variable` so we can use it in the code associated with the arm. We could | |
921 | name this variable `id`, the same as the field, but for this example we’ll use | |
94b46f34 | 922 | a different name. |
83c7162d XL |
923 | |
924 | ```rust | |
925 | enum Message { | |
926 | Hello { id: i32 }, | |
927 | } | |
928 | ||
929 | let msg = Message::Hello { id: 5 }; | |
930 | ||
931 | match msg { | |
932 | Message::Hello { id: id_variable @ 3...7 } => { | |
933 | println!("Found an id in range: {}", id_variable) | |
934 | }, | |
935 | Message::Hello { id: 10...12 } => { | |
936 | println!("Found an id in another range") | |
937 | }, | |
938 | Message::Hello { id } => { | |
939 | println!("Found some other id: {}", id) | |
940 | }, | |
941 | } | |
942 | ``` | |
943 | ||
944 | <span class="caption">Listing 18-32: Using `@` to bind to a value in a pattern | |
945 | while also testing it</span> | |
946 | ||
947 | This example will print `Found an id in range: 5`. By specifying `id_variable | |
948 | @` before the range `3...7`, we’re capturing whatever value matched the range | |
949 | while also testing that the value matched the range pattern. | |
950 | ||
94b46f34 | 951 | In the second arm, where we only have a range specified in the pattern, the code |
83c7162d XL |
952 | associated with the arm doesn’t have a variable that contains the actual value |
953 | of the `id` field. The `id` field’s value could have been 10, 11, or 12, but | |
954 | the code that goes with that pattern doesn’t know which it is. The pattern code | |
955 | isn’t able to use the value from the `id` field, because we haven’t saved the | |
956 | `id` value in a variable. | |
957 | ||
94b46f34 | 958 | In the last arm, where we’ve specified a variable without a range, we do have |
83c7162d XL |
959 | the value available to use in the arm’s code in a variable named `id`. The |
960 | reason is that we’ve used the struct field shorthand syntax. But we haven’t | |
94b46f34 XL |
961 | applied any test to the value in the `id` field in this arm, as we did with the |
962 | first two arms: any value would match this pattern. | |
83c7162d XL |
963 | |
964 | Using `@` lets us test a value and save it in a variable within one pattern. | |
965 | ||
966 | ## Summary | |
967 | ||
968 | Rust’s patterns are very useful in that they help distinguish between different | |
969 | kinds of data. When used in `match` expressions, Rust ensures your patterns | |
970 | cover every possible value, or your program won’t compile. Patterns in `let` | |
971 | statements and function parameters make those constructs more useful, enabling | |
972 | the destructuring of values into smaller parts at the same time as assigning to | |
973 | variables. We can create simple or complex patterns to suit our needs. | |
974 | ||
975 | Next, for the penultimate chapter of the book, we’ll look at some advanced | |
976 | aspects of a variety of Rust’s features. |