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