@@ -183,29 +183,67 @@ possibility in order for the code to be valid. Especially in the case of
183
183
` None ` case, it protects us from assuming that we have a value when we might
184
184
have null, thus making the billion-dollar mistake discussed earlier impossible.
185
185
186
- ### The ` _ ` Placeholder
186
+ ### Catch-all Patterns and the ` _ ` Placeholder
187
+
188
+ Let’s look at an example where we want to take special actions for a few
189
+ particular values, but for all other values take one default action. Imagine
190
+ we’re implementing a game where if you get a value of 3 on a dice roll, your
191
+ player doesn’t move, but instead gets a new fancy hat. If you roll a 7, your
192
+ player loses a fancy hat. For all other values, your player moves that number
193
+ of spaces on the game board. Here’s a ` match ` that implements that logic, with
194
+ the result of the dice roll hardcoded rather than a random value, and all other
195
+ logic represented by functions without bodies because actually implementing
196
+ them is out of scope for this example:
187
197
188
- Rust also has a pattern we can use when we don’t want to list all possible
189
- values. For example, a ` u8 ` can have valid values of 0 through 255. If we only
190
- care about the values 1, 3, 5, and 7, we don’t want to have to list out 0, 2,
191
- 4, 6, 8, 9 all the way up to 255. Fortunately, we don’t have to: we can use the
192
- special pattern ` _ ` instead:
198
+ ``` rust
199
+ {{#rustdoc_include .. / listings / ch06 - enums - and - pattern - matching / no - listing - 15 - binding - catchall / src / main . rs: here }}
200
+ ```
201
+
202
+ For the first two arms, the patterns are the literal values 3 and 7. For the
203
+ last arm that covers every other possible value, the pattern is the variable
204
+ we’ve chosen to name ` other ` . The code that runs for the ` other ` arm uses the
205
+ variable by passing it to the ` move_player ` function.
206
+
207
+ This code compiles, even though we haven’t listed all the possible values a
208
+ ` u8 ` can have, because the last pattern will match all values not specifically
209
+ listed. This catch-all pattern meets the requirement that ` match ` must be
210
+ exhaustive. Note that we have to put the catch-all arm last because the
211
+ patterns are evaluated in order. Rust will warn us if we add arms after a
212
+ catch-all because those later arms would never match!
213
+
214
+ Rust also has a pattern we can use when we don’t want to use the value in the
215
+ catch-all pattern: ` _ ` , which is a special pattern that matches any value and
216
+ does not bind to that value. This tells Rust we aren’t going to use the value,
217
+ so Rust won’t warn us about an unused variable.
218
+
219
+ Let’s change the rules of the game to be that if you roll anything other than
220
+ a 3 or a 7, you must roll again. We don’t need to use the value in that case,
221
+ so we can change our code to use ` _ ` instead of the variable named ` other ` :
193
222
194
223
``` rust
195
- {{#rustdoc_include .. / listings / ch06 - enums - and - pattern - matching / no - listing - 11 - underscore - placeholder / src / main . rs: here }}
224
+ {{#rustdoc_include .. / listings / ch06 - enums - and - pattern - matching / no - listing - 16 - underscore - catchall / src / main . rs: here }}
196
225
```
197
226
198
- The ` _ ` pattern will match any value. By putting it after our other arms, the
199
- ` _ ` will match all the possible cases that aren’t specified before it. The ` () `
200
- is just the unit value (the empty tuple type we mentioned in [ “The Tuple
201
- Type”] [ tuples ] <!-- ignore --> section), so nothing will happen in the ` _ ` case.
202
- As a result, we can say that we want to do nothing for all the possible values
203
- that we don’t list before the ` _ ` placeholder.
227
+ This example also meets the exhaustiveness requirement because we’re explicitly
228
+ ignoring all other values in the last arm; we haven’t forgotten anything.
229
+
230
+ If we change the rules of the game one more time, so that nothing else happens
231
+ on your turn if you roll anything other than a 3 or a 7, we can express that
232
+ by using the unit value (the empty tuple type we mentioned in [ “The Tuple
233
+ Type”] [ tuples ] <!-- ignore --> section) as the code that goes with the ` _ ` arm:
234
+
235
+ ``` rust
236
+ {{#rustdoc_include .. / listings / ch06 - enums - and - pattern - matching / no - listing - 17 - underscore - unit / src / main . rs: here }}
237
+ ```
204
238
205
- However, the ` match ` expression can be a bit wordy in a situation in which we
206
- care about only * one* of the cases. For this situation, Rust provides ` if let ` .
239
+ Here, we’re telling Rust explicitly that we aren’t going to use any other value
240
+ that doesn’t match a pattern in an earlier arm, and we don’t want to run any
241
+ code in this case.
207
242
208
- More about patterns and matching can be found in [ chapter 18] [ ch18-00-patterns ] .
243
+ There’s more about patterns and matching that we’ll cover in [ Chapter
244
+ 18] [ ch18-00-patterns ] <!-- ignore --> . For now, we’re going to move on to the
245
+ ` if let ` syntax, which can be useful in situations where the ` match ` expression
246
+ is a bit wordy.
209
247
210
248
[ tuples ] : ch03-02-data-types.html#the-tuple-type
211
249
[ ch18-00-patterns ] : ch18-00-patterns.html
0 commit comments