Skip to content

Commit 16a17f9

Browse files
committed
Demonstrate variable as catch-all for match. Fixes #1868.
1 parent 340f3c9 commit 16a17f9

File tree

11 files changed

+119
-28
lines changed

11 files changed

+119
-28
lines changed

listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/src/main.rs

-12
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
fn main() {
2+
// ANCHOR: here
3+
let dice_roll = 9;
4+
match dice_roll {
5+
3 => add_fancy_hat(),
6+
7 => remove_fancy_hat(),
7+
other => move_player(other),
8+
}
9+
10+
fn add_fancy_hat() {}
11+
fn remove_fancy_hat() {}
12+
fn move_player(num_spaces: u8) {}
13+
// ANCHOR_END: here
14+
}

listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.lock

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "enums"
3+
version = "0.1.0"
4+
edition = "2018"
5+
6+
[dependencies]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
fn main() {
2+
// ANCHOR: here
3+
let dice_roll = 9;
4+
match dice_roll {
5+
3 => add_fancy_hat(),
6+
7 => remove_fancy_hat(),
7+
_ => reroll(),
8+
}
9+
10+
fn add_fancy_hat() {}
11+
fn remove_fancy_hat() {}
12+
fn reroll() {}
13+
// ANCHOR_END: here
14+
}

listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.lock

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "enums"
3+
version = "0.1.0"
4+
edition = "2018"
5+
6+
[dependencies]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fn main() {
2+
// ANCHOR: here
3+
let dice_roll = 9;
4+
match dice_roll {
5+
3 => add_fancy_hat(),
6+
7 => remove_fancy_hat(),
7+
_ => (),
8+
}
9+
10+
fn add_fancy_hat() {}
11+
fn remove_fancy_hat() {}
12+
// ANCHOR_END: here
13+
}

src/ch06-02-match.md

+54-16
Original file line numberDiff line numberDiff line change
@@ -183,29 +183,67 @@ possibility in order for the code to be valid. Especially in the case of
183183
`None` case, it protects us from assuming that we have a value when we might
184184
have null, thus making the billion-dollar mistake discussed earlier impossible.
185185

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:
187197

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`:
193222

194223
```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}}
196225
```
197226

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+
```
204238

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.
207242

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.
209247

210248
[tuples]: ch03-02-data-types.html#the-tuple-type
211249
[ch18-00-patterns]: ch18-00-patterns.html

0 commit comments

Comments
 (0)