]> git.proxmox.com Git - rustc.git/blame - src/doc/trpl/patterns.md
Imported Upstream version 1.5.0+dfsg1
[rustc.git] / src / doc / trpl / patterns.md
CommitLineData
1a4d82fc
JJ
1% Patterns
2
9346a6ac
AL
3Patterns are quite common in Rust. We use them in [variable
4bindings][bindings], [match statements][match], and other places, too. Let’s go
5on a whirlwind tour of all of the things patterns can do!
6
7[bindings]: variable-bindings.html
8[match]: match.html
1a4d82fc
JJ
9
10A quick refresher: you can match against literals directly, and `_` acts as an
9346a6ac 11‘any’ case:
1a4d82fc 12
9346a6ac 13```rust
85aaf69f 14let x = 1;
1a4d82fc
JJ
15
16match x {
17 1 => println!("one"),
18 2 => println!("two"),
19 3 => println!("three"),
20 _ => println!("anything"),
21}
22```
23
bd371182
AL
24This prints `one`.
25
b039eaaf
SL
26There’s one pitfall with patterns: like anything that introduces a new binding,
27they introduce shadowing. For example:
28
29```rust
30let x = 'x';
31let c = 'c';
32
33match c {
34 x => println!("x: {} c: {}", x, c),
35}
36
37println!("x: {}", x)
38```
39
40This prints:
41
42```text
43x: c c: c
44x: x
45```
46
47In other words, `x =>` matches the pattern and introduces a new binding named
48`x` that’s in scope for the match arm. Because we already have a binding named
49`x`, this new `x` shadows it.
50
9346a6ac
AL
51# Multiple patterns
52
1a4d82fc
JJ
53You can match multiple patterns with `|`:
54
9346a6ac 55```rust
85aaf69f 56let x = 1;
1a4d82fc
JJ
57
58match x {
59 1 | 2 => println!("one or two"),
60 3 => println!("three"),
61 _ => println!("anything"),
62}
63```
64
bd371182
AL
65This prints `one or two`.
66
e9174d1e 67# Destructuring
9346a6ac 68
e9174d1e
SL
69If you have a compound data type, like a [`struct`][struct], you can destructure it
70inside of a pattern:
1a4d82fc 71
9346a6ac 72```rust
e9174d1e
SL
73struct Point {
74 x: i32,
75 y: i32,
1a4d82fc 76}
bd371182 77
e9174d1e 78let origin = Point { x: 0, y: 0 };
bd371182 79
e9174d1e
SL
80match origin {
81 Point { x, y } => println!("({},{})", x, y),
bd371182
AL
82}
83```
84
e9174d1e 85[struct]: structs.html
9346a6ac 86
e9174d1e 87We can use `:` to give a value a different name.
1a4d82fc 88
9346a6ac 89```rust
e9174d1e
SL
90struct Point {
91 x: i32,
92 y: i32,
93}
1a4d82fc 94
e9174d1e
SL
95let origin = Point { x: 0, y: 0 };
96
97match origin {
98 Point { x: x1, y: y1 } => println!("({},{})", x1, y1),
1a4d82fc
JJ
99}
100```
101
e9174d1e 102If we only care about some of the values, we don’t have to give them all names:
bd371182
AL
103
104```rust
e9174d1e
SL
105struct Point {
106 x: i32,
107 y: i32,
bd371182
AL
108}
109
e9174d1e
SL
110let origin = Point { x: 0, y: 0 };
111
112match origin {
113 Point { x, .. } => println!("x is {}", x),
bd371182
AL
114}
115```
116
e9174d1e 117This prints `x is 0`.
bd371182 118
e9174d1e 119You can do this kind of match on any member, not just the first:
bd371182
AL
120
121```rust
e9174d1e
SL
122struct Point {
123 x: i32,
124 y: i32,
125}
bd371182 126
e9174d1e
SL
127let origin = Point { x: 0, y: 0 };
128
129match origin {
130 Point { y, .. } => println!("y is {}", y),
bd371182
AL
131}
132```
133
e9174d1e
SL
134This prints `y is 0`.
135
136This ‘destructuring’ behavior works on any compound data type, like
137[tuples][tuples] or [enums][enums].
138
139[tuples]: primitive-types.html#tuples
140[enums]: enums.html
141
c1a9b12d 142# Ignoring bindings
9346a6ac 143
c1a9b12d
SL
144You can use `_` in a pattern to disregard the type and value.
145For example, here’s a `match` against a `Result<T, E>`:
1a4d82fc 146
9346a6ac 147```rust
c1a9b12d
SL
148# let some_value: Result<i32, &'static str> = Err("There was an error");
149match some_value {
150 Ok(value) => println!("got a value: {}", value),
151 Err(_) => println!("an error occurred"),
152}
153```
154
155In the first arm, we bind the value inside the `Ok` variant to `value`. But
156in the `Err` arm, we use `_` to disregard the specific error, and just print
157a general error message.
158
159`_` is valid in any pattern that creates a binding. This can be useful to
160ignore parts of a larger structure:
161
162```rust
163fn coordinate() -> (i32, i32, i32) {
164 // generate and return some sort of triple tuple
165# (1, 2, 3)
166}
167
168let (x, _, z) = coordinate();
169```
170
171Here, we bind the first and last element of the tuple to `x` and `z`, but
172ignore the middle element.
173
174Similarly, you can use `..` in a pattern to disregard multiple values.
175
176```rust
177enum OptionalTuple {
178 Value(i32, i32, i32),
1a4d82fc
JJ
179 Missing,
180}
181
c1a9b12d 182let x = OptionalTuple::Value(5, -2, 3);
1a4d82fc
JJ
183
184match x {
c1a9b12d
SL
185 OptionalTuple::Value(..) => println!("Got a tuple!"),
186 OptionalTuple::Missing => println!("No such luck."),
1a4d82fc
JJ
187}
188```
189
c1a9b12d 190This prints `Got a tuple!`.
bd371182 191
e9174d1e 192# ref and ref mut
9346a6ac 193
e9174d1e 194If you want to get a [reference][ref], use the `ref` keyword:
1a4d82fc 195
9346a6ac 196```rust
e9174d1e 197let x = 5;
1a4d82fc
JJ
198
199match x {
e9174d1e 200 ref r => println!("Got a reference to {}", r),
1a4d82fc
JJ
201}
202```
203
e9174d1e 204This prints `Got a reference to 5`.
bd371182 205
e9174d1e
SL
206[ref]: references-and-borrowing.html
207
208Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
209keyword _creates_ a reference, for use in the pattern. If you need a mutable
210reference, `ref mut` will work in the same way:
62682a34
SL
211
212```rust
e9174d1e 213let mut x = 5;
62682a34
SL
214
215match x {
e9174d1e 216 ref mut mr => println!("Got a mutable reference to {}", mr),
62682a34
SL
217}
218```
219
e9174d1e 220# Ranges
62682a34 221
e9174d1e 222You can match a range of values with `...`:
62682a34 223
e9174d1e
SL
224```rust
225let x = 1;
62682a34 226
e9174d1e
SL
227match x {
228 1 ... 5 => println!("one through five"),
229 _ => println!("anything"),
230}
62682a34
SL
231```
232
e9174d1e 233This prints `one through five`.
1a4d82fc 234
e9174d1e 235Ranges are mostly used with integers and `char`s:
1a4d82fc 236
9346a6ac 237```rust
e9174d1e 238let x = '💅';
1a4d82fc
JJ
239
240match x {
e9174d1e
SL
241 'a' ... 'j' => println!("early letter"),
242 'k' ... 'z' => println!("late letter"),
243 _ => println!("something else"),
1a4d82fc
JJ
244}
245```
246
e9174d1e 247This prints `something else`.
bd371182 248
e9174d1e 249# Bindings
9346a6ac 250
e9174d1e 251You can bind values to names with `@`:
1a4d82fc 252
9346a6ac 253```rust
e9174d1e 254let x = 1;
1a4d82fc
JJ
255
256match x {
e9174d1e
SL
257 e @ 1 ... 5 => println!("got a range element {}", e),
258 _ => println!("anything"),
1a4d82fc
JJ
259}
260```
261
e9174d1e
SL
262This prints `got a range element 1`. This is useful when you want to
263do a complicated match of part of a data structure:
1a4d82fc 264
9346a6ac 265```rust
e9174d1e
SL
266#[derive(Debug)]
267struct Person {
268 name: Option<String>,
1a4d82fc
JJ
269}
270
e9174d1e
SL
271let name = "Steve".to_string();
272let mut x: Option<Person> = Some(Person { name: Some(name) });
273match x {
274 Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
275 _ => {}
1a4d82fc
JJ
276}
277```
278
e9174d1e 279This prints `Some("Steve")`: we’ve bound the inner `name` to `a`.
bd371182 280
e9174d1e
SL
281If you use `@` with `|`, you need to make sure the name is bound in each part
282of the pattern:
62682a34
SL
283
284```rust
e9174d1e 285let x = 5;
62682a34 286
e9174d1e
SL
287match x {
288 e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
289 _ => println!("anything"),
62682a34
SL
290}
291```
292
e9174d1e
SL
293# Guards
294
295You can introduce ‘match guards’ with `if`:
1a4d82fc 296
9346a6ac 297```rust
e9174d1e
SL
298enum OptionalInt {
299 Value(i32),
300 Missing,
1a4d82fc
JJ
301}
302
e9174d1e 303let x = OptionalInt::Value(5);
1a4d82fc 304
e9174d1e
SL
305match x {
306 OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
307 OptionalInt::Value(..) => println!("Got an int!"),
308 OptionalInt::Missing => println!("No such luck."),
1a4d82fc
JJ
309}
310```
311
e9174d1e 312This prints `Got an int!`.
bd371182 313
e9174d1e 314If you’re using `if` with multiple patterns, the `if` applies to both sides:
1a4d82fc 315
9346a6ac 316```rust
e9174d1e
SL
317let x = 4;
318let y = false;
1a4d82fc 319
e9174d1e
SL
320match x {
321 4 | 5 if y => println!("yes"),
322 _ => println!("no"),
1a4d82fc
JJ
323}
324```
325
e9174d1e 326This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
b039eaaf 327just the `5`. In other words, the precedence of `if` behaves like this:
bd371182 328
e9174d1e
SL
329```text
330(4 | 5) if y => ...
331```
1a4d82fc 332
e9174d1e
SL
333not this:
334
335```text
3364 | (5 if y) => ...
337```
1a4d82fc 338
9346a6ac 339# Mix and Match
1a4d82fc 340
9346a6ac
AL
341Whew! That’s a lot of different ways to match things, and they can all be
342mixed and matched, depending on what you’re doing:
1a4d82fc 343
bd371182 344```rust,ignore
1a4d82fc
JJ
345match x {
346 Foo { x: Some(ref name), y: None } => ...
347}
348```
349
bd371182 350Patterns are very powerful. Make good use of them.