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