]> git.proxmox.com Git - rustc.git/blob - src/doc/book/second-edition/nostarch/chapter18.md
New upstream version 1.26.0+dfsg1
[rustc.git] / src / doc / book / second-edition / nostarch / chapter18.md
1
2 [TOC]
3
4 # Patterns and Matching
5
6 Patterns are a special syntax in Rust for matching against the structure of
7 types, both complex and simple. Using patterns in conjunction with `match`
8 expressions and other constructs gives you more control over a program’s
9 control flow. A pattern consists of some combination of the following:
10
11 * Literals
12 * Destructured arrays, enums, structs, or tuples
13 * Variables
14 * Wildcards
15 * Placeholders
16
17 These components describe the shape of the data we’re working with, which we
18 then match against values to determine whether our program has the correct data
19 to continue running a particular piece of code.
20
21 To use a pattern, we compare it to some value. If the pattern matches the
22 value, we use the value parts in our code. Recall the `match` expressions in
23 Chapter 6 that used patterns, such as the coin sorting machine example. If the
24 value fits the shape of the pattern, we can use the named pieces. If it
25 doesn’t, the code associated with the pattern won’t run.
26
27 This chapter is a reference on all things related to patterns. We’ll cover the
28 valid places to use patterns, the difference between *refutable* and
29 *irrefutable* patterns, and the different kinds of pattern syntax that you
30 might see. By the end of the chapter, you’ll know how to use patterns to
31 express many concepts in a clear way.
32
33 ## All the Places Patterns Can Be Used
34
35 Patterns pop up in a number of places in Rust, and you’ve been using them a lot
36 without realizing it! This section provides you with a reference to all the
37 places where patterns are valid.
38
39 ### `match` Arms
40
41 As discussed in Chapter 6, we use patterns in the arms of `match` expressions.
42 Formally, `match` expressions are defined as the keyword `match`, a value to
43 match on, and one or more match arms that consist of a pattern and an
44 expression to run if the value matches that arm’s pattern, like this:
45
46 ```
47 match VALUE {
48 PATTERN => EXPRESSION,
49 PATTERN => EXPRESSION,
50 PATTERN => EXPRESSION,
51 }
52 ```
53
54 One requirement for `match` expressions is that they need to be *exhaustive* in
55 the sense that all possibilities for the value in the `match` expression must
56 be accounted for. One way to ensure you’ve covered every possibility is to have
57 a catchall pattern for the last arm: for example, a variable name matching any
58 value can never fail and thus covers every remaining case.
59
60 A particular pattern `_` will match anything, but it never binds to a variable,
61 so it’s often used in the last match arm. The `_` pattern can be useful when
62 you want to ignore any value not specified, for example. We’ll cover the `_`
63 pattern in more detail in the “Ignoring Values in a Pattern” section later in
64 this chapter.
65
66 ### Conditional `if let` Expressions
67
68 In Chapter 6 we discussed how to use `if let` expressions mainly as a shorter
69 way to write the equivalent of a `match` that only matches one case.
70 Optionally, `if let` can have a corresponding `else` containing code to run if
71 the pattern in the `if let` doesn’t match.
72
73 Listing 18-1 shows that it’s also possible to mix and match `if let`, `else
74 if`, and `else if let` expressions. Doing so gives us more flexibility than a
75 `match` expression in which we can only express one value to compare with the
76 patterns. Also, the conditions in a series of `if let`, `else if`, `else if
77 let` arms aren’t required to relate to each other.
78
79 The code in Listing 18-1 shows a series of checks for several different
80 conditions that decide what the background color should be. For this example,
81 we’ve created variables with hardcoded values that a real program might receive
82 from user input.
83
84 If the user specifies a favorite color, that color is the background color. If
85 today is Tuesday, the background color will be green. If the user specifies
86 their age as a string and we can parse it as a number successfully, the color
87 is either purple or orange depending on the value of the number. If none of
88 these conditions apply, the background color will be blue:
89
90 Filename: src/main.rs
91
92 ```
93 fn main() {
94 let favorite_color: Option<&str> = None;
95 let is_tuesday = false;
96 let age: Result<u8, _> = "34".parse();
97
98 if let Some(color) = favorite_color {
99 println!("Using your favorite color, {}, as the background", color);
100 } else if is_tuesday {
101 println!("Tuesday is green day!");
102 } else if let Ok(age) = age {
103 if age > 30 {
104 println!("Using purple as the background color");
105 } else {
106 println!("Using orange as the background color");
107 }
108 } else {
109 println!("Using blue as the background color");
110 }
111 }
112 ```
113
114 Listing 18-1: Mixing `if let`, `else if`, `else if let`, and `else`
115
116 This conditional structure lets us support complex requirements. With the
117 hardcoded values we have here, this example will print `Using purple as the
118 background color`.
119
120 You can see that `if let` can also introduce shadowed variables in the same way
121 that `match` arms can: the line `if let Ok(age) = age` introduces a new
122 shadowed `age` variable that contains the value inside the `Ok` variant. This
123 means we need to place the `if age > 30` condition within that block: we can’t
124 combine these two conditions into `if let Ok(age) = age && age > 30`. The
125 shadowed `age` we want to compare to 30 isn’t valid until the new scope starts
126 with the curly bracket.
127
128 The downside of using `if let` expressions is that the compiler doesn’t check
129 exhaustiveness, whereas with `match` expressions it does. If we omitted the
130 last `else` block and therefore missed handling some cases, the compiler would
131 not alert us to the possible logic bug.
132
133 ### `while let` Conditional Loops
134
135 Similar in construction to `if let`, the `while let` conditional loop allows a
136 `while` loop to run for as long as a pattern continues to match. The example in
137 Listing 18-2 shows a `while let` loop that uses a vector as a stack and prints
138 out the values in the vector in the opposite order in which they were pushed:
139
140 ```
141 let mut stack = Vec::new();
142
143 stack.push(1);
144 stack.push(2);
145 stack.push(3);
146
147 while let Some(top) = stack.pop() {
148 println!("{}", top);
149 }
150 ```
151
152 Listing 18-2: Using a `while let` loop to print values for as long as
153 `stack.pop()` returns `Some`
154
155 This example prints 3, 2, and then 1. The `pop` method takes the last element
156 out of the vector and returns `Some(value)`. If the vector is empty, `pop`
157 returns `None`. The `while` loop continues running the code in its block as
158 long as `pop` returns `Some`. When `pop` returns `None`, the loop stops. We can
159 use `while let` to pop every element off our stack.
160
161 ### `for` Loops
162
163 In Chapter 3 we mentioned that the `for` loop is the most common loop
164 construction in Rust code, but we haven’t yet discussed the pattern that `for`
165 takes. In a `for` loop, the pattern is the value that directly follows the
166 keyword `for`, so in `for x in y` the `x` is the pattern.
167
168 Listing 18-3 demonstrates how to use a pattern in a `for` loop to destructure,
169 or break apart, a tuple as part of the `for` loop:
170
171 ```
172 let v = vec!['a', 'b', 'c'];
173
174 for (index, value) in v.iter().enumerate() {
175 println!("{} is at index {}", value, index);
176 }
177 ```
178
179 Listing 18-3: Using a pattern in a `for` loop to destructure a tuple
180
181 The code in Listing 18-3 will print the following:
182
183 ```
184 a is at index 0
185 b is at index 1
186 c is at index 2
187 ```
188
189 We use the `enumerate` method to adapt an iterator to produce a value and that
190 value’s index in the iterator, placed into a tuple. The first call to
191 `enumerate` produces the tuple `(0, 'a')`. When this value is matched to the
192 pattern `(index, value)`, `index` will be `0` and `value` will be `'a'`,
193 printing the first line of the output.
194
195 ### `let` Statements
196
197 Prior to this chapter, we had only explicitly discussed using patterns with
198 `match` and `if let`, but in fact, we’ve used patterns in other places as well,
199 including in `let` statements. For example, consider this straightforward
200 variable assignment with `let`:
201
202 ```
203 let x = 5;
204 ```
205
206 Throughout this book, we’ve used `let` like this hundreds of times, and
207 although you might not have realized it, you were using patterns! More
208 formally, a `let` statement looks like this:
209
210 ```
211 let PATTERN = EXPRESSION;
212 ```
213
214 In statements like `let x = 5;` with a variable name in the `PATTERN` slot, the
215 variable name is just a particularly simple form of a pattern. Rust compares
216 the expression against the pattern and assigns any names it finds. So in the
217 `let x = 5;` example, `x` is a pattern that means “bind what matches here to
218 the variable `x`.” Because the name `x` is the whole pattern, this pattern
219 effectively means “bind everything to the variable `x`, whatever the value is.”
220
221 To see the pattern matching aspect of `let` more clearly, consider Listing
222 18-4, which uses a pattern with `let` to destructure a tuple:
223
224 ```
225 let (x, y, z) = (1, 2, 3);
226 ```
227
228 Listing 18-4: Using a pattern to destructure a tuple and create three variables
229 at once
230
231 Here, we match a tuple against a pattern. Rust compares the value `(1, 2, 3)`
232 to the pattern `(x, y, z)` and sees that the value matches the pattern, so Rust
233 binds `1` to `x`, `2` to `y`, and `3` to `z`. You can think of this tuple
234 pattern as nesting three individual variable patterns inside it.
235
236 If the number of elements in the pattern doesn’t match the number of elements
237 in the tuple, the overall type won’t match and we’ll get a compiler error. For
238 example, Listing 18-5 shows an attempt to destructure a tuple with three
239 elements into two variables, which won’t work:
240
241 ```
242 let (x, y) = (1, 2, 3);
243 ```
244
245 Listing 18-5: Incorrectly constructing a pattern whose variables don’t match
246 the number of elements in the tuple
247
248 Attempting to compile this code results in this type error:
249
250 ```
251 error[E0308]: mismatched types
252 --> src/main.rs:2:9
253 |
254 2 | let (x, y) = (1, 2, 3);
255 | ^^^^^^ expected a tuple with 3 elements, found one with 2 elements
256 |
257 = note: expected type `({integer}, {integer}, {integer})`
258 found type `(_, _)`
259 ```
260
261 If we wanted to ignore one or more of the values in the tuple, we could use `_`
262 or `..` as you’ll see in the “Ignoring Values in a Pattern” section. If the
263 problem is that we have too many variables in the pattern, the solution is to
264 make the types match by removing variables so the number of variables equals
265 the number of elements in the tuple.
266
267 ### Function Parameters
268
269 Function parameters can also be patterns. The code in Listing 18-6, which
270 declares a function named `foo` that takes one parameter named `x` of type
271 `i32`, should by now look familiar:
272
273 ```
274 fn foo(x: i32) {
275 // code goes here
276 }
277 ```
278
279 Listing 18-6: A function signature uses patterns in the parameters
280
281 The `x` part is a pattern! As we did with `let`, we could match a tuple in a
282 function’s arguments to the pattern. Listing 18-7 splits the values in a tuple
283 as we pass it to a function:
284
285 Filename: src/main.rs
286
287 ```
288 fn print_coordinates(&(x, y): &(i32, i32)) {
289 println!("Current location: ({}, {})", x, y);
290 }
291
292 fn main() {
293 let point = (3, 5);
294 print_coordinates(&point);
295 }
296 ```
297
298 Listing 18-7: A function with parameters that destructure a tuple
299
300 This code prints `Current location: (3, 5)`. The values `&(3, 5)` match the
301 pattern `&(x, y)`, so `x` is the value `3` and `y` is the value `5`.
302
303 We can also use patterns in closure parameter lists in the same way as in
304 function parameter lists, because closures are similar to functions, as
305 discussed in Chapter 13.
306
307 At this point, you’ve seen several ways of using patterns, but patterns don’t
308 work the same in every place we can use them. In some places, the patterns must
309 be *irrefutable*, meaning they must match any value provided. In other
310 circumstances, they can be refutable. Let’s discuss these two concepts next.
311
312 ## Refutability: Whether a Pattern Might Fail to Match
313
314 Patterns come in two forms: refutable and irrefutable. Patterns that will match
315 for any possible value passed are *irrefutable*. An example would be `x` in the
316 statement `let x = 5;` because `x` matches anything and therefore cannot fail
317 to match. Patterns that can fail to match for some possible value are
318 *refutable*. An example would be `Some(x)` in the expression `if let Some(x) =
319 a_value`; if the value in `a_value` variable is `None` rather than `Some`, the
320 `Some(x)` pattern would not match.
321
322 Function parameters, `let` statements, and `for` loops can only accept
323 irrefutable patterns, because the program cannot do anything meaningful when
324 values don’t match. The `if let` and `while let` expressions only accept
325 refutable patterns, because by definition they’re intended to handle possible
326 failure: the functionality of a conditional is in its ability to perform
327 differently depending on success or failure.
328
329 In general, you shouldn’t have to worry about the distinction between refutable
330 and irrefutable patterns; however, you do need to be familiar with the concept
331 of refutability so you can respond when you see it in an error message. In
332 those cases, you’ll need to change either the pattern or the construct you’re
333 using the pattern with, depending on the intended behavior of the code.
334
335 Let’s look at an example of what happens when we try to use a refutable pattern
336 where Rust requires an irrefutable pattern and vice versa. Listing 18-8 shows a
337 `let` statement, but for the pattern we’ve specified `Some(x)`, a refutable
338 pattern. As you might expect, this code will error:
339
340 ```
341 let Some(x) = some_option_value;
342 ```
343
344 Listing 18-8: Attempting to use a refutable pattern with `let`
345
346 If `some_option_value` was a `None` value, it would fail to match the pattern
347 `Some(x)`, meaning the pattern is refutable. However, the `let` statement can
348 only accept an irrefutable pattern because there is nothing valid the code can
349 do with a `None` value. At compile time, Rust will complain that we’ve tried to
350 use a refutable pattern where an irrefutable pattern is required:
351
352 ```
353 error[E0005]: refutable pattern in local binding: `None` not covered
354 -->
355 |
356 3 | let Some(x) = some_option_value;
357 | ^^^^^^^ pattern `None` not covered
358 ```
359
360 Because we didn’t cover (and couldn’t cover!) every valid value with the
361 pattern `Some(x)`, Rust rightfully produces a compiler error.
362
363 To fix the problem where we have a refutable pattern where an irrefutable
364 pattern is needed, we can change the code that uses the pattern: instead of
365 using `let`, we can use `if let`. Then if the pattern doesn’t match, the code
366 will just skip the code in the curly brackets, giving it a way to continue
367 validly. Listing 18-9 shows how to fix the code in Listing 18-8:
368
369 ```
370 if let Some(x) = some_option_value {
371 println!("{}", x);
372 }
373 ```
374
375 Listing 18-9: Using `if let` and a block with refutable patterns instead of
376 `let`
377
378 We’ve given the code an out! This code is perfectly valid, although it means we
379 cannot use an irrefutable pattern without receiving an error. If we give `if
380 let` a pattern that will always match, such as `x`, as shown in Listing 18-10,
381 it will error:
382
383 ```
384 if let x = 5 {
385 println!("{}", x);
386 };
387 ```
388
389 Listing 18-10: Attempting to use an irrefutable pattern with `if let`
390
391 Rust complains that it doesn’t make sense to use `if let` with an irrefutable
392 pattern:
393
394 ```
395 error[E0162]: irrefutable if-let pattern
396 --> <anon>:2:8
397 |
398 2 | if let x = 5 {
399 | ^ irrefutable pattern
400 ```
401
402 For this reason, match arms must use refutable patterns, except for the last
403 arm, which should match any remaining values with an irrefutable pattern. Rust
404 allows us to use an irrefutable pattern in a `match` with only one arm, but
405 this syntax isn’t particularly useful and could be replaced with a simpler
406 `let` statement.
407
408 Now that you know where to use patterns and the difference between refutable
409 and irrefutable patterns, let’s cover all the syntax we can use to create
410 patterns.
411
412 ## All the Pattern Syntax
413
414 Throughout the book, you’ve seen examples of many different kinds of patterns.
415 In this section, we gather all the syntax valid in patterns and discuss why you
416 might want to use each of them.
417
418 ### Matching Literals
419
420 As you saw in Chapter 6, you can match patterns against literals directly. The
421 following code gives some examples:
422
423 ```
424 let x = 1;
425
426 match x {
427 1 => println!("one"),
428 2 => println!("two"),
429 3 => println!("three"),
430 _ => println!("anything"),
431 }
432 ```
433
434 This code prints `one` because the value in `x` is 1. This syntax is useful
435 when you want your code to take an action if it gets a particular concrete
436 value.
437
438 ### Matching Named Variables
439
440 Named variables are irrefutable patterns that match any value, and we’ve used
441 them many times in the book. However, there is a complication when you use
442 named variables in `match` expressions. Because `match` starts a new scope,
443 variables declared as part of a pattern inside the `match` expression will
444 shadow those with the same name outside the `match` construct, as is the case
445 with all variables. In Listing 18-11, we declare a variable named `x` with the
446 value `Some(5)` and a variable `y` with the value `10`. We then create a
447 `match` expression on the value `x`. Look at the patterns in the match arms and
448 `println!` at the end, and try to figure out what the code will print before
449 running this code or reading further:
450
451 Filename: src/main.rs
452
453 ```
454 fn main() {
455 let x = Some(5);
456 let y = 10;
457
458 match x {
459 Some(50) => println!("Got 50"),
460 Some(y) => println!("Matched, y = {:?}", y),
461 _ => println!("Default case, x = {:?}", x),
462 }
463
464 println!("at the end: x = {:?}, y = {:?}", x, y);
465 }
466 ```
467
468 Listing 18-11: A `match` expression with an arm that introduces a shadowed
469 variable `y`
470
471 Let’s walk through what happens when the `match` expression runs. The pattern
472 in the first match arm doesn’t match the defined value of `x`, so the code
473 continues.
474
475 The pattern in the second match arm introduces a new variable named `y` that
476 will match any value inside a `Some` value. Because we’re in a new scope inside
477 the `match` expression, this is a new `y` variable, not the `y` we declared at
478 the beginning with the value 10. This new `y` binding will match any value
479 inside a `Some`, which is what we have in `x`. Therefore, this new `y` binds to
480 the inner value of the `Some` in `x`. That value is `5`, so the expression for
481 that arm executes and prints `Matched, y = 5`.
482
483 If `x` had been a `None` value instead of `Some(5)`, the patterns in the first
484 two arms wouldn’t have matched, so the value would have matched to the
485 underscore. We didn’t introduce the `x` variable in the pattern of the
486 underscore arm, so the `x` in the expression is still the outer `x` that hasn’t
487 been shadowed. In this hypothetical case, the `match` would print `Default
488 case, x = None`.
489
490 When the `match` expression is done, its scope ends, and so does the scope of
491 the inner `y`. The last `println!` produces `at the end: x = Some(5), y = 10`.
492
493 To create a `match` expression that compares the values of the outer `x` and
494 `y`, rather than introducing a shadowed variable, we would need to use a match
495 guard conditional instead. We’ll talk about match guards later in the “Extra
496 Conditionals with Match Guards” section.
497
498 ### Multiple Patterns
499
500 In `match` expressions, you can match multiple patterns using the `|` syntax,
501 which means *or*. For example, the following code matches the value of `x`
502 against the match arms, the first of which has an *or* option, meaning if the
503 value of `x` matches either of the values in that arm, that arm’s code will
504 run:
505
506 ```
507 let x = 1;
508
509 match x {
510 1 | 2 => println!("one or two"),
511 3 => println!("three"),
512 _ => println!("anything"),
513 }
514 ```
515
516 This code prints `one or two`.
517
518 ### Matching Ranges of Values with `...`
519
520 The `...` syntax allows us to match to an inclusive range of values. In the
521 following code, when a pattern matches any of the values within the range, that
522 arm will execute:
523
524 ```
525 let x = 5;
526
527 match x {
528 1 ... 5 => println!("one through five"),
529 _ => println!("something else"),
530 }
531 ```
532
533 If `x` is 1, 2, 3, 4, or 5, the first arm will match. This syntax is more
534 convenient than using the `|` operator to express the same idea; instead of `1
535 ... 5`, we would have to specify `1 | 2 | 3 | 4 | 5` if we used `|`. Specifying
536 a range is much shorter, especially if we want to match, say, any number
537 between 1 and 1,000!
538
539 Ranges are only allowed with numeric values or `char` values, because the
540 compiler checks that the range isn’t empty at compile time. The only types for
541 which Rust can tell if a range is empty or not are `char` and numeric values.
542
543 Here is an example using ranges of `char` values:
544
545 ```
546 let x = 'c';
547
548 match x {
549 'a' ... 'j' => println!("early ASCII letter"),
550 'k' ... 'z' => println!("late ASCII letter"),
551 _ => println!("something else"),
552 }
553 ```
554
555 Rust can tell that `c` is within the first pattern’s range and prints `early
556 ASCII letter`.
557
558 ### Destructuring to Break Apart Values
559
560 We can also use patterns to destructure structs, enums, tuples, and references
561 to use different parts of these values. Let’s walk through each value.
562
563 #### Destructuring Structs
564
565 Listing 18-12 shows a `Point` struct with two fields, `x` and `y`, that we can
566 break apart using a pattern with a `let` statement:
567
568 Filename: src/main.rs
569
570 ```
571 struct Point {
572 x: i32,
573 y: i32,
574 }
575
576 fn main() {
577 let p = Point { x: 0, y: 7 };
578
579 let Point { x: a, y: b } = p;
580 assert_eq!(0, a);
581 assert_eq!(7, b);
582 }
583 ```
584
585 Listing 18-12: Destructuring a struct’s fields into separate variables
586
587 This code creates the variables `a` and `b` that match the values of the `x`
588 and `y` fields of the `p` variable. This example shows that the names of the
589 variables in the pattern don’t have to match the field names of the struct. But
590 it’s common to want the variable names to match the field names to make it
591 easier to remember which variables came from which fields.
592
593 Because having variable names match the fields is common and because writing
594 `let Point { x: x, y: y } = p;` contains a lot of duplication, there is a
595 shorthand for patterns that match struct fields: you only need to list the name
596 of the struct field, and the variables created from the pattern will have the
597 same names. Listing 18-13 shows code that behaves in the same way as the code
598 in Listing 18-12, but the variables created in the `let` pattern are `x` and
599 `y` instead of `a` and `b`:
600
601 Filename: src/main.rs
602
603 ```
604 struct Point {
605 x: i32,
606 y: i32,
607 }
608
609 fn main() {
610 let p = Point { x: 0, y: 7 };
611
612 let Point { x, y } = p;
613 assert_eq!(0, x);
614 assert_eq!(7, y);
615 }
616 ```
617
618 Listing 18-13: Destructuring struct fields using struct field shorthand
619
620 This code creates the variables `x` and `y` that match the `x` and `y` fields
621 of the `p` variable. The outcome is that the variables `x` and `y` contain the
622 values from the `p` struct.
623
624 We can also destructure with literal values as part of the struct pattern
625 rather than creating variables for all the fields. Doing so allows us to test
626 some of the fields for particular values while creating variables to
627 destructure the other fields.
628
629 Listing 18-14 shows a `match` expression that separates `Point` values into
630 three cases: points that lie directly on the `x` axis (which is true when `y =
631 0`), on the `y` axis (`x = 0`), or neither:
632
633 Filename: src/main.rs
634
635 ```
636 fn main() {
637 let p = Point { x: 0, y: 7 };
638
639 match p {
640 Point { x, y: 0 } => println!("On the x axis at {}", x),
641 Point { x: 0, y } => println!("On the y axis at {}", y),
642 Point { x, y } => println!("On neither axis: ({}, {})", x, y),
643 }
644 }
645 ```
646
647 Listing 18-14: Destructuring and matching literal values in one pattern
648
649 The first arm will match any point that lies on the `x` axis by specifying that
650 the `y` field matches if its value matches the literal `0`. The pattern still
651 creates an `x` variable that we can use in the code for this arm.
652
653 Similarly, the second arm matches any point on the `y` axis by specifying that
654 the `x` field matches if its value is `0` and creates a variable `y` for the
655 value of the `y` field. The third arm doesn’t specify any literals, so it
656 matches any other `Point` and creates variables for both the `x` and `y` fields.
657
658 In this example, the value `p` matches the second arm by virtue of `x`
659 containing a 0, so this code will print `On the y axis at 7`.
660
661 #### Destructuring Enums
662
663 We’ve destructured enums earlier in this book, for example, when we
664 destructured `Option<i32>` in Listing 6-5 in Chapter 6. One detail we haven’t
665 mentioned explicitly is that the pattern to destructure an enum should
666 correspond to the way the data stored within the enum is defined. As an
667 example, in Listing 18-15 we use the `Message` enum from Listing 6-2 and write
668 a `match` with patterns that will destructure each inner value:
669
670 Filename: src/main.rs
671
672 ```
673 enum Message {
674 Quit,
675 Move { x: i32, y: i32 },
676 Write(String),
677 ChangeColor(i32, i32, i32),
678 }
679
680 fn main() {
681 let msg = Message::ChangeColor(0, 160, 255);
682
683 match msg {
684 Message::Quit => {
685 println!("The Quit variant has no data to destructure.")
686 },
687 Message::Move { x, y } => {
688 println!(
689 "Move in the x direction {} and in the y direction {}",
690 x,
691 y
692 );
693 }
694 Message::Write(text) => println!("Text message: {}", text),
695 Message::ChangeColor(r, g, b) => {
696 println!(
697 "Change the color to red {}, green {}, and blue {}",
698 r,
699 g,
700 b
701 )
702 }
703 }
704 }
705 ```
706
707 Listing 18-15: Destructuring enum variants that hold different kinds of values
708
709 This code will print `Change the color to red 0, green 160, and blue 255`. Try
710 changing the value of `msg` to see the code from the other arms run.
711
712 For enum variants without any data, like `Message::Quit`, we can’t destructure
713 the value any further. We can only match on the literal `Message::Quit` value,
714 and no variables are in that pattern.
715
716 For struct-like enum variants, such as `Message::Move`, we can use a pattern
717 similar to the pattern we specify to match structs. After the variant name, we
718 place curly brackets and then list the fields with variables so we break apart
719 the pieces to use in the code for this arm. Here we use the shorthand form as
720 we did in Listing 18-13.
721
722 For tuple-like enum variants, like `Message::Write` that holds a tuple with one
723 element and `Message::ChangeColor` that holds a tuple with three elements, the
724 pattern is similar to the pattern we specify to match tuples. The number of
725 variables in the pattern must match the number of elements in the variant we’re
726 matching.
727
728 #### Destructuring References
729
730 When the value we’re matching to our pattern contains a reference, we need to
731 destructure the reference from the value, which we can do by specifying a `&`
732 in the pattern. Doing so lets us get a variable holding the value that the
733 reference points to rather than getting a variable that holds the reference.
734 This technique is especially useful in closures where we have iterators that
735 iterate over references, but we want to use the values in the closure rather
736 than the references.
737
738 The example in Listing 18-16 iterates over references to `Point` instances in a
739 vector, and destructures the reference and the struct so we can perform
740 calculations on the `x` and `y` values easily:
741
742 ```
743 let points = vec![
744 Point { x: 0, y: 0 },
745 Point { x: 1, y: 5 },
746 Point { x: 10, y: -3 },
747 ];
748
749 let sum_of_squares: i32 = points
750 .iter()
751 .map(|&Point { x, y }| x * x + y * y)
752 .sum();
753 ```
754
755 Listing 18-16: Destructuring a reference to a struct into the struct field
756 values
757
758 This code gives us the variable `sum_of_squares` holding the value 135, which
759 is the result of squaring the `x` value and the `y` value, adding those
760 together, and then adding the result for each `Point` in the `points` vector to
761 get one number.
762
763 If we had not included the `&` in `&Point { x, y }` we’d get a type mismatch
764 error, because `iter` would then iterate over references to the items in the
765 vector rather than the actual values. The error would look like this:
766
767 ```
768 error[E0308]: mismatched types
769 -->
770 |
771 14 | .map(|Point { x, y }| x * x + y * y)
772 | ^^^^^^^^^^^^ expected &Point, found struct `Point`
773 |
774 = note: expected type `&Point`
775 found type `Point`
776 ```
777
778 This error indicates that Rust was expecting our closure to match `&Point`, but
779 we tried to match directly to a `Point` value, not a reference to a `Point`.
780
781 #### Destructuring Structs and Tuples
782
783 We can mix, match, and nest destructuring patterns in even more complex ways.
784 The following example shows a complicated destructure where we nest structs and
785 tuples inside a tuple, and destructure all the primitive values out:
786
787 ```
788 let ((feet, inches), Point {x, y}) = ((3, 10), Point { x: 3, y: -10 });
789 ```
790
791 This code lets us break complex types into their component parts so we can use
792 the values we’re interested in separately.
793
794 Destructuring with patterns is a convenient way to use pieces of values, such
795 as the value from each field in a struct, separately from each other.
796
797 ### Ignoring Values in a Pattern
798
799 You’ve seen that it’s sometimes useful to ignore values in a pattern, such as
800 in the last arm of a `match`, to get a catchall that doesn’t actually do
801 anything but does account for all remaining possible values. There are a few
802 ways to ignore entire values or parts of values in a pattern: using the `_`
803 pattern (which you’ve seen), using the `_` pattern within another pattern,
804 using a name that starts with an underscore, or using `..` to ignore remaining
805 parts of a value. Let’s explore how and why to use each of these patterns.
806
807 #### Ignoring an Entire Value with `_`
808
809 We’ve used the underscore `_` as a wildcard pattern that will match any value
810 but not bind to the value. Although the underscore `_` pattern is especially
811 useful as the last arm in a `match` expression, we can use it in any pattern,
812 including function parameters, as shown in Listing 18-17:
813
814 Filename: src/main.rs
815
816 ```
817 fn foo(_: i32, y: i32) {
818 println!("This code only uses the y parameter: {}", y);
819 }
820
821 fn main() {
822 foo(3, 4);
823 }
824 ```
825
826 Listing 18-17: Using `_` in a function signature
827
828 This code will completely ignore the value passed as the first argument, `3`,
829 and will print `This code only uses the y parameter: 4`.
830
831 In most cases when you no longer need a particular function parameter, you
832 would change the signature so it doesn’t include the unused parameter. Ignoring
833 a function parameter can be especially useful in some cases: for example, when
834 implementing a trait when you need a certain type signature but the function
835 body in your implementation doesn’t need one of the parameters. The compiler
836 will then not warn about unused function parameters, as it would if you used a
837 name instead.
838
839 #### Ignoring Parts of a Value with a Nested `_`
840
841 We can also use `_` inside another pattern to ignore just part of a value: for
842 example, when we only want to test for part of a value but have no use for the
843 other parts in the corresponding code we want to run. Listing 18-18 shows code
844 responsible for managing a setting’s value. The business requirements are that
845 the user should not be allowed to overwrite an existing customization of a
846 setting but can unset the setting and can give the setting a value if it is
847 currently unset.
848
849 ```
850 let mut setting_value = Some(5);
851 let new_setting_value = Some(10);
852
853 match (setting_value, new_setting_value) {
854 (Some(_), Some(_)) => {
855 println!("Can't overwrite an existing customized value");
856 }
857 _ => {
858 setting_value = new_setting_value;
859 }
860 }
861
862 println!("setting is {:?}", setting_value);
863 ```
864
865 Listing 18-18: Using an underscore within patterns that match `Some` variants
866 when we don’t need to use the value inside the `Some`
867
868 This code will print `Can't overwrite an existing customized value` and then
869 `setting is Some(5)`. In the first match arm, we don’t need to match on or use
870 the values inside either `Some` variant, but we do need to test for the case
871 when `setting_value` and `new_setting_value` are the `Some` variant. In that
872 case, we print why we’re not changing `setting_value`, and it doesn’t get
873 changed.
874
875 In all other cases (if either `setting_value` or `new_setting_value` are
876 `None`) expressed by the `_` pattern in the second arm, we want to allow
877 `new_setting_value` to become `setting_value`.
878
879 We can also use underscores in multiple places within one pattern to ignore
880 particular values. Listing 18-19 shows an example of ignoring the second and
881 fourth values in a tuple of five items:
882
883 ```
884 let numbers = (2, 4, 8, 16, 32);
885
886 match numbers {
887 (first, _, third, _, fifth) => {
888 println!("Some numbers: {}, {}, {}", first, third, fifth)
889 },
890 }
891 ```
892
893 Listing 18-19: Ignoring multiple parts of a tuple
894
895 This code will print `Some numbers: 2, 8, 32`, and the values 4 and 16 will be
896 ignored.
897
898 #### Ignoring an Unused Variable by Starting Its Name with an Underscore
899
900 If you create a variable but don’t use it anywhere, Rust will usually issue a
901 warning because that could be a bug. But sometimes it’s useful to create a
902 variable you won’t use yet, such as when you’re prototyping or just starting a
903 project. In this situation, you can tell Rust not to warn you about the unused
904 variable by starting the name of the variable with an underscore. In Listing
905 18-20, we create two unused variables, but when we run this code, we should
906 only get a warning about one of them:
907
908 Filename: src/main.rs
909
910 ```
911 fn main() {
912 let _x = 5;
913 let y = 10;
914 }
915 ```
916
917 Listing 18-20: Starting a variable name with an underscore to avoid getting
918 unused variable warnings
919
920 Here we get a warning about not using the variable `y`, but we don’t get a
921 warning about not using the variable preceded by the underscore.
922
923 Note that there is a subtle difference between using only `_` and using a name
924 that starts with an underscore. The syntax `_x` still binds the value to the
925 variable, whereas `_` doesn’t bind at all. To show a case where this
926 distinction matters, Listing 18-21 will provide us with an error:
927
928 ```
929 let s = Some(String::from("Hello!"));
930
931 if let Some(_s) = s {
932 println!("found a string");
933 }
934
935 println!("{:?}", s);
936 ```
937
938 Listing 18-21: An unused variable starting with an underscore still binds the
939 value, which might take ownership of the value
940
941 We’ll receive an error because the `s` value will still be moved into `_s`,
942 which prevents us from using `s` again. However, using the underscore by itself
943 doesn’t ever bind to the value. Listing 18-22 will compile without any errors
944 because `s` doesn’t get moved into `_`:
945
946 ```
947 let s = Some(String::from("Hello!"));
948
949 if let Some(_) = s {
950 println!("found a string");
951 }
952
953 println!("{:?}", s);
954 ```
955
956 Listing 18-22: Using an underscore does not bind the value
957
958 This code works just fine because we never bind `s` to anything; it isn’t moved.
959
960 #### Ignoring Remaining Parts of a Value with `..`
961
962 With values that have many parts, we can use the `..` syntax to use only a few
963 parts and ignore the rest, and avoid having to list underscores for each
964 ignored value. The `..` pattern ignores any parts of a value that we haven’t
965 explicitly matched in the rest of the pattern. In Listing 18-23, we have a
966 `Point` struct that holds a coordinate in three-dimensional space. In the
967 `match` expression, we want to operate only on the `x` coordinate and ignore
968 the values in the `y` and `z` fields:
969
970 ```
971 struct Point {
972 x: i32,
973 y: i32,
974 z: i32,
975 }
976
977 let origin = Point { x: 0, y: 0, z: 0 };
978
979 match origin {
980 Point { x, .. } => println!("x is {}", x),
981 }
982 ```
983
984 Listing 18-23: Ignoring all fields of a `Point` except for `x` by using `..`
985
986 We list the `x` value, and then just include the `..` pattern. This is quicker
987 than having to list `y: _` and `z: _`, particularly when we’re working with
988 structs that have lots of fields in situations where only one or two fields are
989 relevant.
990
991 The syntax `..` will expand to as many values as it needs to be. Listing 18-24
992 shows how to use `..` with a tuple:
993
994 Filename: src/main.rs
995
996 ```
997 fn main() {
998 let numbers = (2, 4, 8, 16, 32);
999
1000 match numbers {
1001 (first, .., last) => {
1002 println!("Some numbers: {}, {}", first, last);
1003 },
1004 }
1005 }
1006 ```
1007
1008 Listing 18-24: Matching only the first and last values in a tuple and ignoring
1009 all other values
1010
1011 In this code, the first and last value are matched with `first` and `last`. The
1012 `..` will match and ignore everything in the middle.
1013
1014 However, using `..` must be unambiguous. If it is unclear which values are
1015 intended for matching and which should be ignored, Rust will error. Listing
1016 18-25 shows an example of using `..` ambiguously, so it will not compile:
1017
1018 Filename: src/main.rs
1019
1020 ```
1021 fn main() {
1022 let numbers = (2, 4, 8, 16, 32);
1023
1024 match numbers {
1025 (.., second, ..) => {
1026 println!("Some numbers: {}", second)
1027 },
1028 }
1029 }
1030 ```
1031
1032 Listing 18-25: An attempt to use `..` in an ambiguous way
1033
1034 When we compile this example, we get this error:
1035
1036 ```
1037 error: `..` can only be used once per tuple or tuple struct pattern
1038 --> src/main.rs:5:22
1039 |
1040 5 | (.., second, ..) => {
1041 | ^^
1042 ```
1043
1044 It’s impossible for Rust to determine how many values in the tuple to ignore
1045 before matching a value with `second`, and then how many further values to
1046 ignore thereafter. This code could mean that we want to ignore `2`, bind
1047 `second` to `4`, and then ignore `8`, `16`, and `32`; or that we want to ignore
1048 `2` and `4`, bind `second` to `8`, and then ignore `16` and `32`; and so forth.
1049 The variable name `second` doesn’t mean anything special to Rust, so we get a
1050 compiler error because using `..` in two places like this is ambiguous.
1051
1052 ### `ref` and `ref mut` to Create References in Patterns
1053
1054 Let’s look at using `ref` to make references so ownership of the values isn’t
1055 moved to variables in the pattern. Usually, when you match against a pattern,
1056 the variables introduced by the pattern are bound to a value. Rust’s ownership
1057 rules mean the value will be moved into the `match` or wherever you’re using
1058 the pattern. Listing 18-26 shows an example of a `match` that has a pattern
1059 with a variable and then usage of the entire value in the `println!` statement
1060 later, after the `match`. This code will fail to compile because ownership of
1061 part of the `robot_name` value is transferred to the `name` variable in the
1062 pattern of the first `match` arm:
1063
1064 ```
1065 let robot_name = Some(String::from("Bors"));
1066
1067 match robot_name {
1068 Some(name) => println!("Found a name: {}", name),
1069 None => (),
1070 }
1071
1072 println!("robot_name is: {:?}", robot_name);
1073 ```
1074
1075 Listing 18-26: Creating a variable in a `match` arm pattern takes ownership of
1076 the value
1077
1078 Because ownership of part of `robot_name` has been moved to `name`, we can no
1079 longer use `robot_name` in the `println!` after the `match` because
1080 `robot_name` no longer has ownership.
1081
1082 To fix this code, we want to make the `Some(name)` pattern *borrow* that part
1083 of `robot_name` rather than taking ownership. You’ve already seen that, outside
1084 of patterns, the way to borrow a value is to create a reference using `&`, so
1085 you might think the solution is changing `Some(name)` to `Some(&name)`.
1086
1087 However, as you saw in the “Destructuring to Break Apart Values” section, the
1088 syntax `&` in patterns does not *create* a reference but *matches* an existing
1089 reference in the value. Because `&` already has that meaning in patterns, we
1090 can’t use `&` to create a reference in a pattern.
1091
1092 Instead, to create a reference in a pattern, we use the `ref` keyword before
1093 the new variable, as shown in Listing 18-27:
1094
1095 ```
1096 let robot_name = Some(String::from("Bors"));
1097
1098 match robot_name {
1099 Some(ref name) => println!("Found a name: {}", name),
1100 None => (),
1101 }
1102
1103 println!("robot_name is: {:?}", robot_name);
1104 ```
1105
1106 Listing 18-27: Creating a reference so a pattern variable does not take
1107 ownership of a value
1108
1109 This example will compile because the value in the `Some` variant in
1110 `robot_name` is not moved into the `match`; the `match` only took a reference
1111 to the data in `robot_name` rather than moving it.
1112
1113 To create a mutable reference so we’re able to mutate a value matched in a
1114 pattern, we use `ref mut` instead of `&mut`. The reason is, again, that in
1115 patterns, the latter is for matching existing mutable references, not creating
1116 new ones. Listing 18-28 shows an example of a pattern creating a mutable
1117 reference:
1118
1119 ```
1120 let mut robot_name = Some(String::from("Bors"));
1121
1122 match robot_name {
1123 Some(ref mut name) => *name = String::from("Another name"),
1124 None => (),
1125 }
1126
1127 println!("robot_name is: {:?}", robot_name);
1128 ```
1129
1130 Listing 18-28: Creating a mutable reference to a value as part of a pattern
1131 using `ref mut`
1132
1133 This example will compile and print `robot_name is: Some("Another name")`.
1134 Because `name` is a mutable reference, we need to dereference within the match
1135 arm code using the `*` operator to mutate the value.
1136
1137 ### Extra Conditionals with Match Guards
1138
1139 A *match guard* is an additional `if` condition specified after the pattern in
1140 a `match` arm that must also match, along with the pattern matching, for that
1141 arm to be chosen. Match guards are useful for expressing more complex ideas
1142 than a pattern alone allows.
1143
1144 The condition can use variables created in the pattern. Listing 18-29 shows a
1145 `match` where the first arm has the pattern `Some(x)` and also has a match
1146 guard of `if x < 5`:
1147
1148 ```
1149 let num = Some(4);
1150
1151 match num {
1152 Some(x) if x < 5 => println!("less than five: {}", x),
1153 Some(x) => println!("{}", x),
1154 None => (),
1155 }
1156 ```
1157
1158 Listing 18-29: Adding a match guard to a pattern
1159
1160 This example will print `less than five: 4`. When `num` is compared to the
1161 pattern in the first arm, it matches, because `Some(4)` matches `Some(x)`. Then
1162 the match guard checks whether the value in `x` is less than `5`, and because
1163 it is, the first arm is selected.
1164
1165 If `num` had been `Some(10)` instead, the match guard in the first arm would
1166 have been false because 10 is not less than 5. Rust would then go to the second
1167 arm, which would match because the second arm doesn’t have a match guard and
1168 therefore matches any `Some` variant.
1169
1170 There is no way to express the `if x < 5` condition within a pattern, so the
1171 match guard gives us the ability to express this logic.
1172
1173 In Listing 18-11, we mentioned that we could use match guards to solve our
1174 pattern shadowing problem. Recall that a new variable was created inside the
1175 pattern in the `match` expression instead of using the variable outside the
1176 `match`. That new variable meant we couldn’t test against the value of the
1177 outer variable. Listing 18-30 shows how we can use a match guard to fix this
1178 problem:
1179
1180 Filename: src/main.rs
1181
1182 ```
1183 fn main() {
1184 let x = Some(5);
1185 let y = 10;
1186
1187 match x {
1188 Some(50) => println!("Got 50"),
1189 Some(n) if n == y => println!("Matched, n = {:?}", n),
1190 _ => println!("Default case, x = {:?}", x),
1191 }
1192
1193 println!("at the end: x = {:?}, y = {:?}", x, y);
1194 }
1195 ```
1196
1197 Listing 18-30: Using a match guard to test for equality with an outer variable
1198
1199 This code will now print `Default case, x = Some(5)`. The pattern in the second
1200 match arm doesn’t introduce a new variable `y` that would shadow the outer `y`,
1201 meaning we can use the outer `y` in the match guard. Instead of specifying the
1202 pattern as `Some(y)`, which would have shadowed the outer `y`, we specify
1203 `Some(n)`. This creates a new variable `n` that doesn’t shadow anything because
1204 there is no `n` variable outside the `match`.
1205
1206 The match guard `if n == y` is not a pattern and therefore doesn’t introduce
1207 new variables. This `y` *is* the outer `y` rather than a new shadowed `y`, and
1208 we can look for a value that has the same value as the outer `y` by comparing
1209 `n` to `y`.
1210
1211 You can also use the *or* operator `|` in a match guard to specify multiple
1212 patterns; the match guard condition will apply to all the patterns. Listing
1213 18-31 shows the precedence of combining a match guard with a pattern that uses
1214 `|`. The important part of this example is that the `if y` match guard applies
1215 to `4`, `5`, *and* `6`, even though it might look like `if y` only applies to
1216 `6`:
1217
1218 ```
1219 let x = 4;
1220 let y = false;
1221
1222 match x {
1223 4 | 5 | 6 if y => println!("yes"),
1224 _ => println!("no"),
1225 }
1226 ```
1227
1228 Listing 18-31: Combining multiple patterns with a match guard
1229
1230 The match condition states that the arm only matches if the value of `x` is
1231 equal to `4`, `5`, or `6` *and* if `y` is `true`. When this code runs, the
1232 pattern of the first arm matches because `x` is `4`, but the match guard `if y`
1233 is false, so the first arm is not chosen. The code moves on to the second arm,
1234 which does match, and this program prints `no`. The reason is that the `if`
1235 condition applies to the whole pattern `4 | 5 | 6`, not only to the last value
1236 `6`. In other words, the precedence of a match guard in relation to a pattern
1237 behaves like this:
1238
1239 ```
1240 (4 | 5 | 6) if y => ...
1241 ```
1242
1243 rather than this:
1244
1245 ```
1246 4 | 5 | (6 if y) => ...
1247 ```
1248
1249 After running the code, the precedence behavior is evident: if the match guard
1250 was only applied to the final value in the list of values specified using the
1251 `|` operator, the arm would have matched and the program would have printed
1252 `yes`.
1253
1254 ### `@` Bindings
1255
1256 The *at* operator `@` lets us create a variable that holds a value at the same
1257 time we’re testing that value to see whether it matches a pattern. Listing
1258 18-32 shows an example where we want to test that a `Message::Hello` `id` field
1259 is within the range `3...7`. But we also want to bind the value to the variable
1260 `id_variable` so we can use it in the code associated with the arm. We could
1261 name this variable `id`, the same as the field, but for this example we’ll use
1262 a different name:
1263
1264 ```
1265 enum Message {
1266 Hello { id: i32 },
1267 }
1268
1269 let msg = Message::Hello { id: 5 };
1270
1271 match msg {
1272 Message::Hello { id: id_variable @ 3...7 } => {
1273 println!("Found an id in range: {}", id_variable)
1274 },
1275 Message::Hello { id: 10...12 } => {
1276 println!("Found an id in another range")
1277 },
1278 Message::Hello { id } => {
1279 println!("Found some other id: {}", id)
1280 },
1281 }
1282 ```
1283
1284 Listing 18-32: Using `@` to bind to a value in a pattern while also testing it
1285
1286 This example will print `Found an id in range: 5`. By specifying `id_variable
1287 @` before the range `3...7`, we’re capturing whatever value matched the range
1288 while also testing that the value matched the range pattern.
1289
1290 In the second arm where we only have a range specified in the pattern, the code
1291 associated with the arm doesn’t have a variable that contains the actual value
1292 of the `id` field. The `id` field’s value could have been 10, 11, or 12, but
1293 the code that goes with that pattern doesn’t know which it is. The pattern code
1294 isn’t able to use the value from the `id` field, because we haven’t saved the
1295 `id` value in a variable.
1296
1297 In the last arm where we’ve specified a variable without a range, we do have
1298 the value available to use in the arm’s code in a variable named `id`. The
1299 reason is that we’ve used the struct field shorthand syntax. But we haven’t
1300 applied any test to the value in the `id` field in this arm, like we did with
1301 the first two arms: any value would match this pattern.
1302
1303 Using `@` lets us test a value and save it in a variable within one pattern.
1304
1305 ## Summary
1306
1307 Rust’s patterns are very useful in that they help distinguish between different
1308 kinds of data. When used in `match` expressions, Rust ensures your patterns
1309 cover every possible value, or your program won’t compile. Patterns in `let`
1310 statements and function parameters make those constructs more useful, enabling
1311 the destructuring of values into smaller parts at the same time as assigning to
1312 variables. We can create simple or complex patterns to suit our needs.
1313
1314 Next, for the penultimate chapter of the book, we’ll look at some advanced
1315 aspects of a variety of Rust’s features.