]> git.lizzy.rs Git - rust.git/blob - src/doc/trpl/patterns.md
Auto merge of #22517 - brson:relnotes, r=Gankro
[rust.git] / src / doc / trpl / patterns.md
1 % Patterns
2
3 We've made use of patterns a few times in the guide: first with `let` bindings,
4 then with `match` statements. Let's go on a whirlwind tour of all of the things
5 patterns can do!
6
7 A quick refresher: you can match against literals directly, and `_` acts as an
8 *any* case:
9
10 ```{rust}
11 let x = 1;
12
13 match x {
14     1 => println!("one"),
15     2 => println!("two"),
16     3 => println!("three"),
17     _ => println!("anything"),
18 }
19 ```
20
21 You can match multiple patterns with `|`:
22
23 ```{rust}
24 let x = 1;
25
26 match x {
27     1 | 2 => println!("one or two"),
28     3 => println!("three"),
29     _ => println!("anything"),
30 }
31 ```
32
33 You can match a range of values with `...`:
34
35 ```{rust}
36 let x = 1;
37
38 match x {
39     1 ... 5 => println!("one through five"),
40     _ => println!("anything"),
41 }
42 ```
43
44 Ranges are mostly used with integers and single characters.
45
46 If you're matching multiple things, via a `|` or a `...`, you can bind
47 the value to a name with `@`:
48
49 ```{rust}
50 let x = 1;
51
52 match x {
53     e @ 1 ... 5 => println!("got a range element {}", e),
54     _ => println!("anything"),
55 }
56 ```
57
58 If you're matching on an enum which has variants, you can use `..` to
59 ignore the value and type in the variant:
60
61 ```{rust}
62 enum OptionalInt {
63     Value(i32),
64     Missing,
65 }
66
67 let x = OptionalInt::Value(5);
68
69 match x {
70     OptionalInt::Value(..) => println!("Got an int!"),
71     OptionalInt::Missing => println!("No such luck."),
72 }
73 ```
74
75 You can introduce *match guards* with `if`:
76
77 ```{rust}
78 enum OptionalInt {
79     Value(i32),
80     Missing,
81 }
82
83 let x = OptionalInt::Value(5);
84
85 match x {
86     OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
87     OptionalInt::Value(..) => println!("Got an int!"),
88     OptionalInt::Missing => println!("No such luck."),
89 }
90 ```
91
92 If you're matching on a pointer, you can use the same syntax as you declared it
93 with. First, `&`:
94
95 ```{rust}
96 let x = &5;
97
98 match x {
99     &val => println!("Got a value: {}", val),
100 }
101 ```
102
103 Here, the `val` inside the `match` has type `i32`. In other words, the left-hand
104 side of the pattern destructures the value. If we have `&5`, then in `&val`, `val`
105 would be `5`.
106
107 If you want to get a reference, use the `ref` keyword:
108
109 ```{rust}
110 let x = 5;
111
112 match x {
113     ref r => println!("Got a reference to {}", r),
114 }
115 ```
116
117 Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
118 keyword _creates_ a reference, for use in the pattern. If you need a mutable
119 reference, `ref mut` will work in the same way:
120
121 ```{rust}
122 let mut x = 5;
123
124 match x {
125     ref mut mr => println!("Got a mutable reference to {}", mr),
126 }
127 ```
128
129 If you have a struct, you can destructure it inside of a pattern:
130
131 ```{rust}
132 # #![allow(non_shorthand_field_patterns)]
133 struct Point {
134     x: i32,
135     y: i32,
136 }
137
138 let origin = Point { x: 0, y: 0 };
139
140 match origin {
141     Point { x: x, y: y } => println!("({},{})", x, y),
142 }
143 ```
144
145 If we only care about some of the values, we don't have to give them all names:
146
147 ```{rust}
148 # #![allow(non_shorthand_field_patterns)]
149 struct Point {
150     x: i32,
151     y: i32,
152 }
153
154 let origin = Point { x: 0, y: 0 };
155
156 match origin {
157     Point { x: x, .. } => println!("x is {}", x),
158 }
159 ```
160
161 You can do this kind of match on any member, not just the first:
162
163 ```{rust}
164 # #![allow(non_shorthand_field_patterns)]
165 struct Point {
166     x: i32,
167     y: i32,
168 }
169
170 let origin = Point { x: 0, y: 0 };
171
172 match origin {
173     Point { y: y, .. } => println!("y is {}", y),
174 }
175 ```
176
177 If you want to match against a slice or array, you can use `&`:
178
179 ```{rust}
180 fn main() {
181     let v = vec!["match_this", "1"];
182
183     match &v[] {
184         ["match_this", second] => println!("The second element is {}", second),
185         _ => {},
186     }
187 }
188 ```
189
190 Whew! That's a lot of different ways to match things, and they can all be
191 mixed and matched, depending on what you're doing:
192
193 ```{rust,ignore}
194 match x {
195     Foo { x: Some(ref name), y: None } => ...
196 }
197 ```
198
199 Patterns are very powerful.  Make good use of them.