]> git.proxmox.com Git - rustc.git/blame - src/doc/book/src/ch18-03-pattern-syntax.md
New upstream version 1.63.0+dfsg1
[rustc.git] / src / doc / book / src / ch18-03-pattern-syntax.md
CommitLineData
13cf67c4
XL
1## Pattern Syntax
2
923072b8
FG
3In this section, we gather all the syntax valid in patterns and discuss why and
4when you might want to use each one.
13cf67c4
XL
5
6### Matching Literals
7
8As you saw in Chapter 6, you can match patterns against literals directly. The
9following code gives some examples:
10
11```rust
74b04a01 12{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-01-literals/src/main.rs:here}}
13cf67c4
XL
13```
14
15This code prints `one` because the value in `x` is 1. This syntax is useful
16when you want your code to take an action if it gets a particular concrete
17value.
18
19### Matching Named Variables
20
21Named variables are irrefutable patterns that match any value, and we’ve used
22them many times in the book. However, there is a complication when you use
23named variables in `match` expressions. Because `match` starts a new scope,
24variables declared as part of a pattern inside the `match` expression will
25shadow those with the same name outside the `match` construct, as is the case
26with all variables. In Listing 18-11, we declare a variable named `x` with the
27value `Some(5)` and a variable `y` with the value `10`. We then create a
28`match` expression on the value `x`. Look at the patterns in the match arms and
29`println!` at the end, and try to figure out what the code will print before
30running this code or reading further.
31
32<span class="filename">Filename: src/main.rs</span>
33
34```rust
74b04a01 35{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-11/src/main.rs:here}}
13cf67c4
XL
36```
37
38<span class="caption">Listing 18-11: A `match` expression with an arm that
39introduces a shadowed variable `y`</span>
40
41Let’s walk through what happens when the `match` expression runs. The pattern
42in the first match arm doesn’t match the defined value of `x`, so the code
43continues.
44
45The pattern in the second match arm introduces a new variable named `y` that
46will match any value inside a `Some` value. Because we’re in a new scope inside
47the `match` expression, this is a new `y` variable, not the `y` we declared at
48the beginning with the value 10. This new `y` binding will match any value
49inside a `Some`, which is what we have in `x`. Therefore, this new `y` binds to
50the inner value of the `Some` in `x`. That value is `5`, so the expression for
51that arm executes and prints `Matched, y = 5`.
52
53If `x` had been a `None` value instead of `Some(5)`, the patterns in the first
54two arms wouldn’t have matched, so the value would have matched to the
55underscore. We didn’t introduce the `x` variable in the pattern of the
56underscore arm, so the `x` in the expression is still the outer `x` that hasn’t
57been shadowed. In this hypothetical case, the `match` would print `Default
58case, x = None`.
59
60When the `match` expression is done, its scope ends, and so does the scope of
61the inner `y`. The last `println!` produces `at the end: x = Some(5), y = 10`.
62
63To create a `match` expression that compares the values of the outer `x` and
64`y`, rather than introducing a shadowed variable, we would need to use a match
9fa01778
XL
65guard conditional instead. We’ll talk about match guards later in the [“Extra
66Conditionals with Match Guards”](#extra-conditionals-with-match-guards)<!--
67ignore --> section.
13cf67c4
XL
68
69### Multiple Patterns
70
71In `match` expressions, you can match multiple patterns using the `|` syntax,
923072b8
FG
72which is the pattern *or* operator. For example, in the following code we match
73the value of `x` against the match arms, the first of which has an *or* option,
74meaning if the value of `x` matches either of the values in that arm, that
75arm’s code will run:
13cf67c4
XL
76
77```rust
74b04a01 78{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/src/main.rs:here}}
13cf67c4
XL
79```
80
81This code prints `one or two`.
82
e1599b0c 83### Matching Ranges of Values with `..=`
13cf67c4 84
e1599b0c 85The `..=` syntax allows us to match to an inclusive range of values. In the
923072b8
FG
86following code, when a pattern matches any of the values within the given
87range, that arm will execute:
13cf67c4
XL
88
89```rust
74b04a01 90{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-03-ranges/src/main.rs:here}}
13cf67c4
XL
91```
92
93If `x` is 1, 2, 3, 4, or 5, the first arm will match. This syntax is more
923072b8
FG
94convenient for multiple match values than using the `|` operator to express the
95same idea; if we were to use `|` we would have to specify `1 | 2 | 3 | 4 | 5`.
48663c56
XL
96Specifying a range is much shorter, especially if we want to match, say, any
97number between 1 and 1,000!
13cf67c4 98
923072b8
FG
99The compiler checks that the range isn’t empty at compile time, and because the
100only types for which Rust can tell if a range is empty or not are `char` and
101numeric values, ranges are only allowed with numeric or `char` values.
13cf67c4
XL
102
103Here is an example using ranges of `char` values:
104
105```rust
74b04a01 106{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/src/main.rs:here}}
13cf67c4
XL
107```
108
5e7ed085 109Rust can tell that `'c'` is within the first pattern’s range and prints `early
13cf67c4
XL
110ASCII letter`.
111
112### Destructuring to Break Apart Values
113
5099ac24
FG
114We can also use patterns to destructure structs, enums, and tuples to use
115different parts of these values. Let’s walk through each value.
13cf67c4
XL
116
117#### Destructuring Structs
118
119Listing 18-12 shows a `Point` struct with two fields, `x` and `y`, that we can
120break apart using a pattern with a `let` statement.
121
122<span class="filename">Filename: src/main.rs</span>
123
124```rust
74b04a01 125{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-12/src/main.rs}}
13cf67c4
XL
126```
127
128<span class="caption">Listing 18-12: Destructuring a struct’s fields into
129separate variables</span>
130
131This code creates the variables `a` and `b` that match the values of the `x`
69743fb6 132and `y` fields of the `p` struct. This example shows that the names of the
923072b8
FG
133variables in the pattern don’t have to match the field names of the struct.
134However, it’s common to match the variable names to the field names to make it
135easier to remember which variables came from which fields. Because of this
136common usage, and because writing `let Point { x: x, y: y } = p;` contains a
137lot of duplication, Rust has a shorthand for patterns that match struct fields:
138you only need to list the name of the struct field, and the variables created
139from the pattern will have the same names. Listing 18-13 behaves in the same
140way as the code in Listing 18-12, but the variables created in the `let`
141pattern are `x` and `y` instead of `a` and `b`.
13cf67c4
XL
142
143<span class="filename">Filename: src/main.rs</span>
144
145```rust
74b04a01 146{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-13/src/main.rs}}
13cf67c4
XL
147```
148
149<span class="caption">Listing 18-13: Destructuring struct fields using struct
150field shorthand</span>
151
152This code creates the variables `x` and `y` that match the `x` and `y` fields
153of the `p` variable. The outcome is that the variables `x` and `y` contain the
154values from the `p` struct.
155
156We can also destructure with literal values as part of the struct pattern
157rather than creating variables for all the fields. Doing so allows us to test
158some of the fields for particular values while creating variables to
159destructure the other fields.
160
923072b8
FG
161In Listing 18-14, we have a `match` expression that separates `Point` values
162into three cases: points that lie directly on the `x` axis (which is true when
163`y = 0`), on the `y` axis (`x = 0`), or neither.
13cf67c4
XL
164
165<span class="filename">Filename: src/main.rs</span>
166
167```rust
74b04a01 168{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-14/src/main.rs:here}}
13cf67c4
XL
169```
170
171<span class="caption">Listing 18-14: Destructuring and matching literal values
172in one pattern</span>
173
174The first arm will match any point that lies on the `x` axis by specifying that
175the `y` field matches if its value matches the literal `0`. The pattern still
176creates an `x` variable that we can use in the code for this arm.
177
178Similarly, the second arm matches any point on the `y` axis by specifying that
179the `x` field matches if its value is `0` and creates a variable `y` for the
180value of the `y` field. The third arm doesn’t specify any literals, so it
181matches any other `Point` and creates variables for both the `x` and `y` fields.
182
183In this example, the value `p` matches the second arm by virtue of `x`
184containing a 0, so this code will print `On the y axis at 7`.
185
923072b8
FG
186Remember that a `match` expression stops checking arms once it has found the
187first matching pattern, so even though `Point { x: 0, y: 0}` is on the `x` axis
188and the `y` axis, this code would only print `On the x axis at 0`.
189
13cf67c4
XL
190#### Destructuring Enums
191
923072b8
FG
192We've destructured enums in this book (for example, Listing 6-5 in Chapter 6),
193but haven’t yet explicitly discussed that the pattern to destructure an enum
194corresponds to the way the data stored within the enum is defined. As an
13cf67c4
XL
195example, in Listing 18-15 we use the `Message` enum from Listing 6-2 and write
196a `match` with patterns that will destructure each inner value.
197
198<span class="filename">Filename: src/main.rs</span>
199
200```rust
74b04a01 201{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-15/src/main.rs}}
13cf67c4
XL
202```
203
204<span class="caption">Listing 18-15: Destructuring enum variants that hold
205different kinds of values</span>
206
207This code will print `Change the color to red 0, green 160, and blue 255`. Try
208changing the value of `msg` to see the code from the other arms run.
209
210For enum variants without any data, like `Message::Quit`, we can’t destructure
211the value any further. We can only match on the literal `Message::Quit` value,
212and no variables are in that pattern.
213
214For struct-like enum variants, such as `Message::Move`, we can use a pattern
215similar to the pattern we specify to match structs. After the variant name, we
216place curly brackets and then list the fields with variables so we break apart
217the pieces to use in the code for this arm. Here we use the shorthand form as
218we did in Listing 18-13.
219
220For tuple-like enum variants, like `Message::Write` that holds a tuple with one
221element and `Message::ChangeColor` that holds a tuple with three elements, the
222pattern is similar to the pattern we specify to match tuples. The number of
223variables in the pattern must match the number of elements in the variant we’re
224matching.
225
9fa01778 226#### Destructuring Nested Structs and Enums
13cf67c4 227
923072b8
FG
228So far, our examples have all been matching structs or enums one level deep,
229but matching can work on nested items too! For example, we can refactor the
230code in Listing 18-15 to support RGB and HSV colors in the `ChangeColor`
231message, as shown in Listing 18-16.
13cf67c4
XL
232
233```rust
74b04a01 234{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-16/src/main.rs}}
13cf67c4
XL
235```
236
9fa01778 237<span class="caption">Listing 18-16: Matching on nested enums</span>
13cf67c4 238
9fa01778 239The pattern of the first arm in the `match` expression matches a
532ac7d7
XL
240`Message::ChangeColor` enum variant that contains a `Color::Rgb` variant; then
241the pattern binds to the three inner `i32` values. The pattern of the second
242arm also matches a `Message::ChangeColor` enum variant, but the inner enum
923072b8
FG
243matches `Color::Hsv` instead. We can specify these complex conditions in one
244`match` expression, even though two enums are involved.
13cf67c4
XL
245
246#### Destructuring Structs and Tuples
247
248We can mix, match, and nest destructuring patterns in even more complex ways.
249The following example shows a complicated destructure where we nest structs and
250tuples inside a tuple and destructure all the primitive values out:
251
252```rust
74b04a01 253{{#rustdoc_include ../listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/src/main.rs:here}}
13cf67c4
XL
254```
255
256This code lets us break complex types into their component parts so we can use
257the values we’re interested in separately.
258
259Destructuring with patterns is a convenient way to use pieces of values, such
260as the value from each field in a struct, separately from each other.
261
262### Ignoring Values in a Pattern
263
264You’ve seen that it’s sometimes useful to ignore values in a pattern, such as
265in the last arm of a `match`, to get a catchall that doesn’t actually do
266anything but does account for all remaining possible values. There are a few
267ways to ignore entire values or parts of values in a pattern: using the `_`
268pattern (which you’ve seen), using the `_` pattern within another pattern,
269using a name that starts with an underscore, or using `..` to ignore remaining
270parts of a value. Let’s explore how and why to use each of these patterns.
271
272#### Ignoring an Entire Value with `_`
273
923072b8
FG
274We’ve used the underscore as a wildcard pattern that will match any value but
275not bind to the value. This is especially useful as the last arm in a `match`
276expression, but we can also use it in any pattern, including function
277parameters, as shown in Listing 18-17.
13cf67c4
XL
278
279<span class="filename">Filename: src/main.rs</span>
280
281```rust
74b04a01 282{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-17/src/main.rs}}
13cf67c4
XL
283```
284
285<span class="caption">Listing 18-17: Using `_` in a function signature</span>
286
923072b8 287This code will completely ignore the value `3` passed as the first argument,
13cf67c4
XL
288and will print `This code only uses the y parameter: 4`.
289
290In most cases when you no longer need a particular function parameter, you
291would change the signature so it doesn’t include the unused parameter. Ignoring
923072b8
FG
292a function parameter can be especially useful in cases when, for example,
293you're implementing a trait when you need a certain type signature but the
294function body in your implementation doesn’t need one of the parameters. You
295then avoid getting a compiler warning about unused function parameters, as you
296would if you used a name instead.
13cf67c4
XL
297
298#### Ignoring Parts of a Value with a Nested `_`
299
300We can also use `_` inside another pattern to ignore just part of a value, for
301example, when we want to test for only part of a value but have no use for the
302other parts in the corresponding code we want to run. Listing 18-18 shows code
303responsible for managing a setting’s value. The business requirements are that
304the user should not be allowed to overwrite an existing customization of a
532ac7d7 305setting but can unset the setting and give it a value if it is currently unset.
13cf67c4
XL
306
307```rust
74b04a01 308{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-18/src/main.rs:here}}
13cf67c4
XL
309```
310
311<span class="caption">Listing 18-18: Using an underscore within patterns that
312match `Some` variants when we don’t need to use the value inside the
313`Some`</span>
314
315This code will print `Can't overwrite an existing customized value` and then
316`setting is Some(5)`. In the first match arm, we don’t need to match on or use
317the values inside either `Some` variant, but we do need to test for the case
318when `setting_value` and `new_setting_value` are the `Some` variant. In that
923072b8 319case, we print the reason for not changing `setting_value`, and it doesn’t get
13cf67c4
XL
320changed.
321
322In all other cases (if either `setting_value` or `new_setting_value` are
323`None`) expressed by the `_` pattern in the second arm, we want to allow
324`new_setting_value` to become `setting_value`.
325
326We can also use underscores in multiple places within one pattern to ignore
327particular values. Listing 18-19 shows an example of ignoring the second and
328fourth values in a tuple of five items.
329
330```rust
74b04a01 331{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-19/src/main.rs:here}}
13cf67c4
XL
332```
333
334<span class="caption">Listing 18-19: Ignoring multiple parts of a tuple</span>
335
336This code will print `Some numbers: 2, 8, 32`, and the values 4 and 16 will be
337ignored.
338
339#### Ignoring an Unused Variable by Starting Its Name with `_`
340
341If you create a variable but don’t use it anywhere, Rust will usually issue a
923072b8
FG
342warning because an unused variable could be a bug. However, sometimes it’s
343useful to be able to create a variable you won’t use yet, such as when you’re
344prototyping or just starting a project. In this situation, you can tell Rust
345not to warn you about the unused variable by starting the name of the variable
346with an underscore. In Listing 18-20, we create two unused variables, but when
347we compile this code, we should only get a warning about one of them.
13cf67c4
XL
348
349<span class="filename">Filename: src/main.rs</span>
350
351```rust
74b04a01 352{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-20/src/main.rs}}
13cf67c4
XL
353```
354
355<span class="caption">Listing 18-20: Starting a variable name with an
356underscore to avoid getting unused variable warnings</span>
357
358Here we get a warning about not using the variable `y`, but we don’t get a
923072b8 359warning about not using `_x`.
13cf67c4
XL
360
361Note that there is a subtle difference between using only `_` and using a name
362that starts with an underscore. The syntax `_x` still binds the value to the
363variable, whereas `_` doesn’t bind at all. To show a case where this
364distinction matters, Listing 18-21 will provide us with an error.
365
366```rust,ignore,does_not_compile
74b04a01 367{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-21/src/main.rs:here}}
13cf67c4
XL
368```
369
370<span class="caption">Listing 18-21: An unused variable starting with an
371underscore still binds the value, which might take ownership of the value</span>
372
373We’ll receive an error because the `s` value will still be moved into `_s`,
374which prevents us from using `s` again. However, using the underscore by itself
375doesn’t ever bind to the value. Listing 18-22 will compile without any errors
376because `s` doesn’t get moved into `_`.
377
378```rust
74b04a01 379{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-22/src/main.rs:here}}
13cf67c4
XL
380```
381
382<span class="caption">Listing 18-22: Using an underscore does not bind the
383value</span>
384
385This code works just fine because we never bind `s` to anything; it isn’t moved.
386
387#### Ignoring Remaining Parts of a Value with `..`
388
923072b8 389With values that have many parts, we can use the `..` syntax to use specific
13cf67c4
XL
390parts and ignore the rest, avoiding the need to list underscores for each
391ignored value. The `..` pattern ignores any parts of a value that we haven’t
392explicitly matched in the rest of the pattern. In Listing 18-23, we have a
393`Point` struct that holds a coordinate in three-dimensional space. In the
394`match` expression, we want to operate only on the `x` coordinate and ignore
395the values in the `y` and `z` fields.
396
397```rust
74b04a01 398{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-23/src/main.rs:here}}
13cf67c4
XL
399```
400
401<span class="caption">Listing 18-23: Ignoring all fields of a `Point` except
402for `x` by using `..`</span>
403
404We list the `x` value and then just include the `..` pattern. This is quicker
405than having to list `y: _` and `z: _`, particularly when we’re working with
406structs that have lots of fields in situations where only one or two fields are
407relevant.
408
409The syntax `..` will expand to as many values as it needs to be. Listing 18-24
410shows how to use `..` with a tuple.
411
412<span class="filename">Filename: src/main.rs</span>
413
414```rust
74b04a01 415{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-24/src/main.rs}}
13cf67c4
XL
416```
417
418<span class="caption">Listing 18-24: Matching only the first and last values in
419a tuple and ignoring all other values</span>
420
421In this code, the first and last value are matched with `first` and `last`. The
422`..` will match and ignore everything in the middle.
423
424However, using `..` must be unambiguous. If it is unclear which values are
425intended for matching and which should be ignored, Rust will give us an error.
426Listing 18-25 shows an example of using `..` ambiguously, so it will not
427compile.
428
429<span class="filename">Filename: src/main.rs</span>
430
431```rust,ignore,does_not_compile
74b04a01 432{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-25/src/main.rs}}
13cf67c4
XL
433```
434
435<span class="caption">Listing 18-25: An attempt to use `..` in an ambiguous
436way</span>
437
438When we compile this example, we get this error:
439
f035d41b 440```console
74b04a01 441{{#include ../listings/ch18-patterns-and-matching/listing-18-25/output.txt}}
13cf67c4
XL
442```
443
444It’s impossible for Rust to determine how many values in the tuple to ignore
445before matching a value with `second` and then how many further values to
446ignore thereafter. This code could mean that we want to ignore `2`, bind
447`second` to `4`, and then ignore `8`, `16`, and `32`; or that we want to ignore
448`2` and `4`, bind `second` to `8`, and then ignore `16` and `32`; and so forth.
449The variable name `second` doesn’t mean anything special to Rust, so we get a
450compiler error because using `..` in two places like this is ambiguous.
451
452### Extra Conditionals with Match Guards
453
923072b8
FG
454A *match guard* is an additional `if` condition, specified after the pattern in
455a `match` arm, that must also match for that arm to be chosen. Match guards are
456useful for expressing more complex ideas than a pattern alone allows.
13cf67c4
XL
457
458The condition can use variables created in the pattern. Listing 18-26 shows a
459`match` where the first arm has the pattern `Some(x)` and also has a match
5099ac24 460guard of `if x % 2 == 0` (which will be true if the number is even).
13cf67c4
XL
461
462```rust
74b04a01 463{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-26/src/main.rs:here}}
13cf67c4
XL
464```
465
466<span class="caption">Listing 18-26: Adding a match guard to a pattern</span>
467
5099ac24 468This example will print `The number 4 is even`. When `num` is compared to the
13cf67c4 469pattern in the first arm, it matches, because `Some(4)` matches `Some(x)`. Then
5099ac24
FG
470the match guard checks whether the remainder of dividing `x` by 2 is equal to
4710, and because it is, the first arm is selected.
472
473If `num` had been `Some(5)` instead, the match guard in the first arm would
474have been false because the remainder of 5 divided by 2 is 1, which is not
475equal to 0. Rust would then go to the second arm, which would match because the
476second arm doesn’t have a match guard and therefore matches any `Some` variant.
477
478There is no way to express the `if x % 2 == 0` condition within a pattern, so
479the match guard gives us the ability to express this logic. The downside of
480this additional expressiveness is that the compiler doesn't try to check for
481exhaustiveness when match guard expressions are involved.
13cf67c4
XL
482
483In Listing 18-11, we mentioned that we could use match guards to solve our
923072b8 484pattern-shadowing problem. Recall that we created a new variable inside the
13cf67c4
XL
485pattern in the `match` expression instead of using the variable outside the
486`match`. That new variable meant we couldn’t test against the value of the
9fa01778 487outer variable. Listing 18-27 shows how we can use a match guard to fix this
13cf67c4
XL
488problem.
489
490<span class="filename">Filename: src/main.rs</span>
491
492```rust
74b04a01 493{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-27/src/main.rs}}
13cf67c4
XL
494```
495
496<span class="caption">Listing 18-27: Using a match guard to test for equality
497with an outer variable</span>
498
499This code will now print `Default case, x = Some(5)`. The pattern in the second
500match arm doesn’t introduce a new variable `y` that would shadow the outer `y`,
501meaning we can use the outer `y` in the match guard. Instead of specifying the
502pattern as `Some(y)`, which would have shadowed the outer `y`, we specify
503`Some(n)`. This creates a new variable `n` that doesn’t shadow anything because
504there is no `n` variable outside the `match`.
505
506The match guard `if n == y` is not a pattern and therefore doesn’t introduce
507new variables. This `y` *is* the outer `y` rather than a new shadowed `y`, and
508we can look for a value that has the same value as the outer `y` by comparing
509`n` to `y`.
510
511You can also use the *or* operator `|` in a match guard to specify multiple
512patterns; the match guard condition will apply to all the patterns. Listing
923072b8
FG
51318-28 shows the precedence when combining a pattern that uses `|` with a match
514guard. The important part of this example is that the `if y` match guard
515applies to `4`, `5`, *and* `6`, even though it might look like `if y` only
516applies to `6`.
13cf67c4
XL
517
518```rust
74b04a01 519{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-28/src/main.rs:here}}
13cf67c4
XL
520```
521
9fa01778 522<span class="caption">Listing 18-28: Combining multiple patterns with a match
13cf67c4
XL
523guard</span>
524
525The match condition states that the arm only matches if the value of `x` is
526equal to `4`, `5`, or `6` *and* if `y` is `true`. When this code runs, the
527pattern of the first arm matches because `x` is `4`, but the match guard `if y`
528is false, so the first arm is not chosen. The code moves on to the second arm,
529which does match, and this program prints `no`. The reason is that the `if`
530condition applies to the whole pattern `4 | 5 | 6`, not only to the last value
531`6`. In other words, the precedence of a match guard in relation to a pattern
532behaves like this:
533
534```text
535(4 | 5 | 6) if y => ...
536```
537
538rather than this:
539
540```text
5414 | 5 | (6 if y) => ...
542```
543
544After running the code, the precedence behavior is evident: if the match guard
545were applied only to the final value in the list of values specified using the
546`|` operator, the arm would have matched and the program would have printed
547`yes`.
548
549### `@` Bindings
550
923072b8
FG
551The *at* operator `@` lets us create a variable that holds a value at the same
552time as we’re testing that value for a pattern match. In Listing 18-29, we want
553to test that a `Message::Hello` `id` field is within the range `3..=7`. We also
554want to bind the value to the variable `id_variable` so we can use it in the
555code associated with the arm. We could name this variable `id`, the same as the
556field, but for this example we’ll use a different name.
13cf67c4
XL
557
558```rust
74b04a01 559{{#rustdoc_include ../listings/ch18-patterns-and-matching/listing-18-29/src/main.rs:here}}
13cf67c4
XL
560```
561
9fa01778 562<span class="caption">Listing 18-29: Using `@` to bind to a value in a pattern
13cf67c4
XL
563while also testing it</span>
564
565This example will print `Found an id in range: 5`. By specifying `id_variable
e1599b0c 566@` before the range `3..=7`, we’re capturing whatever value matched the range
13cf67c4
XL
567while also testing that the value matched the range pattern.
568
569In the second arm, where we only have a range specified in the pattern, the code
570associated with the arm doesn’t have a variable that contains the actual value
571of the `id` field. The `id` field’s value could have been 10, 11, or 12, but
572the code that goes with that pattern doesn’t know which it is. The pattern code
573isn’t able to use the value from the `id` field, because we haven’t saved the
574`id` value in a variable.
575
576In the last arm, where we’ve specified a variable without a range, we do have
577the value available to use in the arm’s code in a variable named `id`. The
578reason is that we’ve used the struct field shorthand syntax. But we haven’t
579applied any test to the value in the `id` field in this arm, as we did with the
580first two arms: any value would match this pattern.
581
582Using `@` lets us test a value and save it in a variable within one pattern.
583
13cf67c4
XL
584## Summary
585
923072b8
FG
586Rust’s patterns are very useful in distinguishing between different kinds of
587data. When used in `match` expressions, Rust ensures your patterns cover every
588possible value, or your program won’t compile. Patterns in `let` statements and
589function parameters make those constructs more useful, enabling the
590destructuring of values into smaller parts at the same time as assigning to
13cf67c4
XL
591variables. We can create simple or complex patterns to suit our needs.
592
593Next, for the penultimate chapter of the book, we’ll look at some advanced
594aspects of a variety of Rust’s features.