Skip to content

Commit 73c1a0d

Browse files
Merge pull request #469 from rust-lang/ch18-patterns
Chapter 18: Patterns
2 parents 2a9b2a1 + 4ca9e51 commit 73c1a0d

6 files changed

+1071
-334
lines changed

second-edition/dictionary.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ dereferencing
7070
DerefMut
7171
destructor
7272
destructure
73+
destructured
7374
destructures
7475
destructuring
7576
Destructuring
@@ -232,6 +233,7 @@ refactoring
232233
refcell
233234
RefCell
234235
RefMut
236+
refutability
235237
repr
236238
retweet
237239
ripgrep
@@ -298,6 +300,7 @@ tradeoff
298300
tradeoffs
299301
TrafficLight
300302
trpl
303+
tuesday
301304
tuple
302305
tuples
303306
typeof
@@ -328,6 +331,7 @@ wasn
328331
WeatherForecast
329332
WebSocket
330333
whitespace
334+
wildcard
331335
wildcards
332336
workflow
333337
workspace

second-edition/src/SUMMARY.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@
9999

100100
## Advanced Topics
101101

102-
- [Patterns](ch18-00-patterns.md) (perhaps an appendix?)
102+
- [Patterns Match the Structure of Values](ch18-00-patterns.md)
103+
- [All the Places Patterns May be Used](ch18-01-all-the-places-for-patterns.md)
104+
- [Refutability: Whether a Pattern Might Fail to Match](ch18-02-refutability.md)
105+
- [All the Pattern Syntax](ch18-03-pattern-syntax.md)
103106

104107
- [Advanced Features](ch19-00-advanced-features.md)
105108
- [Unsafe Rust](ch19-01-unsafe-rust.md)
Lines changed: 19 additions & 333 deletions
Original file line numberDiff line numberDiff line change
@@ -1,333 +1,19 @@
1-
# Patterns
2-
3-
We've actually used patterns a few times so far: they're used in `let`
4-
statements, in function parameters, and in the `match` expression. Patterns have
5-
a lot more abilities than we have demonstrated so far, so we'll cover some of
6-
the most commonly used ones in this section. Any of these abilities work in any
7-
place where a pattern is used.
8-
9-
## `let` statements
10-
11-
A basic `let` statement has this form:
12-
13-
```text
14-
let PATTERN = EXPRESSION;
15-
```
16-
17-
We've seen statements like `let x = 5;` with a variable name in the `PATTERN`
18-
slot; a variable name is just a particularly humble form of pattern.
19-
20-
Let’s try a more complex pattern. Change our example program to this:
21-
22-
<span class="filename">Filename: src/main.rs</span>
23-
24-
```rust
25-
fn main() {
26-
let (x, y) = (5, 6);
27-
28-
println!("The value of x is: {}", x);
29-
println!("The value of y is: {}", y);
30-
}
31-
```
32-
33-
And run it with `cargo run`:
34-
35-
```text
36-
$ cargo run
37-
Compiling patterns v0.1.0 (file:///projects/patterns)
38-
Running `target/debug/patterns`
39-
The value of x is: 5
40-
The value of y is: 6
41-
```
42-
43-
We’ve created two variables with one `let`! Here’s our pattern:
44-
45-
```text
46-
(x, y)
47-
```
48-
49-
And here’s the value:
50-
51-
```text
52-
(5, 6)
53-
```
54-
55-
As you can see, the two line up visually, and so `let` binds the variable `x`
56-
to the value `5` and `y` to `6`. We could have used two `let` statements as
57-
well:
58-
59-
```rust
60-
fn main() {
61-
let x = 5;
62-
let y = 6;
63-
}
64-
```
65-
66-
In simple cases like this, two `let`s may be clearer, but in others, creating
67-
multiple variables at once is nice. As we become more proficient in Rust, we’ll
68-
figure out which style is better, but it’s mostly a judgment call.
69-
70-
## Type annotations
71-
72-
Most of the time, Rust uses *type inference*, meaning that it attempts to infer
73-
the types of your variables rather than you having to declare them explicitly
74-
even though Rust is a statically typed language. Occasionally, Rust won't have
75-
enough information to infer the type of your value, and you will need to add a
76-
type annotation in with the pattern.
77-
78-
Here’s what a `let` statement with a *type annotation* looks like:
79-
80-
```rust
81-
let x: i32 = 5;
82-
```
83-
84-
We can add a colon, followed by the type name. Here’s the structure of a `let`
85-
statement with a type annotation:
86-
87-
```text
88-
let PATTERN: TYPE = VALUE;
89-
```
90-
91-
Note that the colon and the `TYPE` go *after* the `PATTERN`, not in the pattern
92-
itself. As an example, here’s our more complex pattern with two variables:
93-
94-
```rust
95-
let (x, y): (i32, i32) = (5, 6);
96-
```
97-
98-
Just like we match up the `VALUE` with the `PATTERN`, we match up the `TYPE`
99-
with the `PATTERN`.
100-
101-
## Literals & _
102-
103-
You can match against literals directly, and `_` acts as an ‘any’ case:
104-
105-
```rust
106-
let x = 1;
107-
108-
match x {
109-
1 => println!("one"),
110-
2 => println!("two"),
111-
3 => println!("three"),
112-
_ => println!("anything"),
113-
}
114-
```
115-
116-
This prints `one`.
117-
118-
# Multiple patterns
119-
120-
You can match multiple patterns with `|`:
121-
122-
```rust
123-
let x = 1;
124-
125-
match x {
126-
1 | 2 => println!("one or two"),
127-
3 => println!("three"),
128-
_ => println!("anything"),
129-
}
130-
```
131-
132-
This prints `one or two`.
133-
134-
## ref and ref mut
135-
136-
Usually, when you match against a pattern, variables are bound to a value.
137-
This means you'll end up moving the value into the `match`:
138-
139-
```rust,ignore
140-
let name = Some(String::from("Bors"));
141-
142-
match name {
143-
Some(name) => println!("Found a name: {}", name),
144-
None => (),
145-
}
146-
147-
// name is moved here. This line will fail to compile:
148-
println!("name is: {:?}", name);
149-
```
150-
151-
If you'd prefer to bind `name` to a reference, use the `ref` keyword:
152-
153-
```rust
154-
let name = Some(String::from("Bors"));
155-
156-
match name {
157-
Some(ref name) => println!("Found a name: {}", name),
158-
None => (),
159-
}
160-
161-
// name is not moved here; the match only took a reference to its data rather
162-
// than moving it. This will work:
163-
println!("name is: {:?}", name);
164-
```
165-
166-
And for a mutable reference, `ref mut`:
167-
168-
```rust
169-
let mut name = Some(String::from("Bors"));
170-
171-
match name {
172-
Some(ref mut name) => *name = String::from("Another name"),
173-
None => (),
174-
}
175-
176-
// name is not moved here; the match only took a reference to its data rather
177-
// than moving it
178-
println!("name is: {:?}", name);
179-
```
180-
181-
## Destructuring
182-
183-
Patterns can be used to destructure structs and enums:
184-
185-
```rust
186-
struct Point {
187-
x: i32,
188-
y: i32,
189-
}
190-
191-
let origin = Point { x: 0, y: 0 };
192-
193-
let Point { x, y } = origin;
194-
```
195-
196-
This brings `x` and `y` variables into scope, matching the `x` and `y` of
197-
`origin`. While it can be unusual in `let`, this is the same principle of
198-
patterns in `match`:
199-
200-
```rust
201-
struct Point {
202-
x: i32,
203-
y: i32,
204-
}
205-
206-
let origin = Point { x: 0, y: 0 };
207-
208-
match origin {
209-
Point { x, y } => { }, // variables x and y are created here
210-
}
211-
```
212-
213-
## Shadowing
214-
215-
As with all variables, those declared by a pattern will shadow variables
216-
outside of the `match` construct:
217-
218-
```rust
219-
let x = Some(5);
220-
221-
match x {
222-
Some(x) => { }, // x is an i32 here, not an Option<i32>
223-
None => (),
224-
}
225-
```
226-
227-
## Ignoring values
228-
229-
We discussed using `_` as a whole pattern to ignore it above, but you can
230-
also use `_` inside of another pattern to ignore just part of it:
231-
232-
```rust
233-
let x = Some(5);
234-
235-
match x {
236-
Some(_) => println!("got a Some and I don't care what's inside"),
237-
None => (),
238-
}
239-
```
240-
241-
Or like this:
242-
243-
```rust
244-
let numbers = (2, 4, 8, 16, 32);
245-
246-
match numbers {
247-
(first, _, third, _, fifth) => println!("Some numbers: {}, {}, {}", first, third, fifth),
248-
}
249-
```
250-
251-
If you want, you can use `..` to ignore all of the parts you haven't defined:
252-
253-
```rust
254-
struct Point {
255-
x: i32,
256-
y: i32,
257-
z: i32,
258-
}
259-
260-
let origin = Point { x: 0, y: 0, z: 0 };
261-
262-
match origin {
263-
Point { x, .. } => { }, // y and z are ignored
264-
}
265-
```
266-
267-
## Ranges
268-
269-
You can match a range of values with `...`:
270-
271-
```rust
272-
let x = 5;
273-
274-
match x {
275-
1 ... 5 => println!("one through five"),
276-
_ => println!("something else"),
277-
}
278-
```
279-
280-
Ranges are usually used with integers or `char`s:
281-
282-
```rust
283-
let x = 'c';
284-
285-
match x {
286-
'a' ... 'j' => println!("early ASCII letter"),
287-
'k' ... 'z' => println!("late ASCII letter"),
288-
_ => println!("something else"),
289-
}
290-
```
291-
292-
## Guards
293-
294-
You can introduce ‘match guards’ with `if`:
295-
296-
```rust
297-
let x = Some(5);
298-
299-
match x {
300-
Some(x) if x < 5 => println!("less than five: {}", x),
301-
Some(x) => println!("{}", x),
302-
None => (),
303-
}
304-
```
305-
306-
If you’re using if with multiple patterns, the if applies to both sides:
307-
308-
```rust
309-
let x = 4;
310-
let y = false;
311-
312-
match x {
313-
4 | 5 if y => println!("yes"),
314-
_ => println!("no"),
315-
}
316-
```
317-
318-
This prints `no`, because the if applies to the whole of `4 | 5`, and not to only
319-
the `5`. In other words, the precedence of if behaves like this:
320-
321-
```text
322-
(4 | 5) if y => ...
323-
```
324-
325-
not this:
326-
327-
```text
328-
4 | (5 if y) => ...
329-
```
330-
331-
## Bindings
332-
333-
You can bind values to names with `@`:
1+
# Patterns Match the Structure of Values
2+
3+
Patterns are a special syntax within Rust for matching against the structure of
4+
our types, complex or simple. A pattern is made up of some combination of
5+
literals; destructured arrays, enums, structs, or tuples; variables, wildcards,
6+
and placeholders. These pieces describe the "shape" of the data we're working
7+
with.
8+
9+
We use a pattern by taking some value and comparing it against the pattern. If
10+
the pattern matches our value, we do something with the value parts. Recall in
11+
Chapter 6 when we discussed the `match` expression that uses patterns like a
12+
coin sorting machine. We can name pieces within the shape, like we named the
13+
state that appeared on quarters in Chapter 6, and if the data fits the shape,
14+
we can use the named pieces.
15+
16+
This chapter is a reference on all things related to patterns. We'll cover the
17+
valid places to use patterns, the difference between *refutable* and
18+
*irrefutable* patterns, and the different kinds of pattern syntax that you
19+
might see.

0 commit comments

Comments
 (0)