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