]>
Commit | Line | Data |
---|---|---|
13cf67c4 XL |
1 | ## Concise Control Flow with `if let` |
2 | ||
3 | The `if let` syntax lets you combine `if` and `let` into a less verbose way to | |
4 | handle values that match one pattern while ignoring the rest. Consider the | |
94222f64 XL |
5 | program in Listing 6-6 that matches on an `Option<u8>` value in the `config_max` |
6 | variable but only wants to execute code if the value is the `Some` variant. | |
13cf67c4 XL |
7 | |
8 | ```rust | |
74b04a01 | 9 | {{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs:here}} |
13cf67c4 XL |
10 | ``` |
11 | ||
12 | <span class="caption">Listing 6-6: A `match` that only cares about executing | |
94222f64 | 13 | code when the value is `Some`</span> |
13cf67c4 | 14 | |
a2a8927a XL |
15 | If the value is `Some`, we print out the value in the `Some` variant by binding |
16 | the value to the variable `max` in the pattern. We don’t want to do anything | |
17 | with the `None` value. To satisfy the `match` expression, we have to add `_ => | |
18 | ()` after processing just one variant, which is annoying boilerplate code to | |
19 | add. | |
13cf67c4 XL |
20 | |
21 | Instead, we could write this in a shorter way using `if let`. The following | |
22 | code behaves the same as the `match` in Listing 6-6: | |
23 | ||
24 | ```rust | |
74b04a01 | 25 | {{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/src/main.rs:here}} |
13cf67c4 XL |
26 | ``` |
27 | ||
69743fb6 XL |
28 | The syntax `if let` takes a pattern and an expression separated by an equal |
29 | sign. It works the same way as a `match`, where the expression is given to the | |
94222f64 XL |
30 | `match` and the pattern is its first arm. In this case, the pattern is |
31 | `Some(max)`, and the `max` binds to the value inside the `Some`. We can then | |
32 | use `max` in the body of the `if let` block in the same way as we used `max` in | |
33 | the corresponding `match` arm. The code in the `if let` block isn’t run if the | |
34 | value doesn’t match the pattern. | |
13cf67c4 | 35 | |
69743fb6 XL |
36 | Using `if let` means less typing, less indentation, and less boilerplate code. |
37 | However, you lose the exhaustive checking that `match` enforces. Choosing | |
38 | between `match` and `if let` depends on what you’re doing in your particular | |
39 | situation and whether gaining conciseness is an appropriate trade-off for | |
40 | losing exhaustive checking. | |
13cf67c4 XL |
41 | |
42 | In other words, you can think of `if let` as syntax sugar for a `match` that | |
43 | runs code when the value matches one pattern and then ignores all other values. | |
44 | ||
45 | We can include an `else` with an `if let`. The block of code that goes with the | |
46 | `else` is the same as the block of code that would go with the `_` case in the | |
47 | `match` expression that is equivalent to the `if let` and `else`. Recall the | |
48 | `Coin` enum definition in Listing 6-4, where the `Quarter` variant also held a | |
49 | `UsState` value. If we wanted to count all non-quarter coins we see while also | |
50 | announcing the state of the quarters, we could do that with a `match` | |
51 | expression like this: | |
52 | ||
53 | ```rust | |
74b04a01 | 54 | {{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs:here}} |
13cf67c4 XL |
55 | ``` |
56 | ||
57 | Or we could use an `if let` and `else` expression like this: | |
58 | ||
59 | ```rust | |
74b04a01 | 60 | {{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs:here}} |
13cf67c4 XL |
61 | ``` |
62 | ||
63 | If you have a situation in which your program has logic that is too verbose to | |
64 | express using a `match`, remember that `if let` is in your Rust toolbox as well. | |
65 | ||
66 | ## Summary | |
67 | ||
68 | We’ve now covered how to use enums to create custom types that can be one of a | |
69 | set of enumerated values. We’ve shown how the standard library’s `Option<T>` | |
70 | type helps you use the type system to prevent errors. When enum values have | |
71 | data inside them, you can use `match` or `if let` to extract and use those | |
72 | values, depending on how many cases you need to handle. | |
73 | ||
74 | Your Rust programs can now express concepts in your domain using structs and | |
75 | enums. Creating custom types to use in your API ensures type safety: the | |
76 | compiler will make certain your functions get only values of the type each | |
77 | function expects. | |
78 | ||
79 | In order to provide a well-organized API to your users that is straightforward | |
80 | to use and only exposes exactly what your users will need, let’s now turn to | |
81 | Rust’s modules. |