mirror of
https://github.com/rust-lang-cn/book-cn.git
synced 2025-01-24 16:10:25 +08:00
Remove Patterns subsection; to become a top-level later chapter
See https://github.com/rust-lang/book/pull/167
This commit is contained in:
parent
2e18fde173
commit
ed5a22ea24
@ -25,8 +25,7 @@
|
||||
- [Enums](ch06-00-enums.md)
|
||||
- [Option](ch06-01-option.md)
|
||||
- [Match](ch06-02-match.md)
|
||||
- [Patterns](ch06-03-patterns.md)
|
||||
- [if let](ch06-04-if-let.md)
|
||||
- [if let](ch06-03-if-let.md)
|
||||
|
||||
- [MANY MORE CHAPTERS COMING SOON]()
|
||||
|
||||
|
@ -1,197 +0,0 @@
|
||||
# Patterns
|
||||
|
||||
We've mentioned 'patterns' a few times so far: they're used in `let` bindings,
|
||||
in function arguments, and in `match` expressions. Patterns have a lot of
|
||||
abilities, so in this section, we'll cover some of the most commonly used ones.
|
||||
Any of these abilities work in any place where a pattern is used.
|
||||
|
||||
Let's start with an example that is similar to the last example in the previous
|
||||
section:
|
||||
|
||||
```rust
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
1 => println!("one"),
|
||||
3 => println!("three"),
|
||||
5 => println!("five"),
|
||||
7 => println!("seven"),
|
||||
_ => println!("anything else"),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `one`. If we change `x` to have the value 4, this would print
|
||||
`anything else`.
|
||||
|
||||
# Multiple patterns
|
||||
|
||||
What if we wanted to print the same thing for 1, 3, and 5? We could do:
|
||||
|
||||
```rust
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
1 => println!("an odd number less than six"),
|
||||
3 => println!("an odd number less than six"),
|
||||
5 => println!("an odd number less than six"),
|
||||
7 => println!("seven"),
|
||||
_ => println!("anything else"),
|
||||
}
|
||||
```
|
||||
|
||||
But that repeats the string "an odd number less than six" multiple times. If we
|
||||
had to change that string, it would be annoying to have to change it in three
|
||||
places to make 1, 3, and 5 still have the same behavior.
|
||||
|
||||
Instead, we could match multiple patterns with `|`:
|
||||
|
||||
```rust
|
||||
let x = 1;
|
||||
|
||||
match x {
|
||||
1 | 3 | 5 => println!("an odd number less than six"),
|
||||
7 => println!("seven"),
|
||||
_ => println!("anything else"),
|
||||
}
|
||||
```
|
||||
|
||||
This match statement has the same functionality as the previous one, but we only
|
||||
had to write the common `println!` once!
|
||||
|
||||
## Ranges
|
||||
|
||||
Another way to have multiple values match the same arm is using a range. If,
|
||||
instead of the above where we treated 1, 3, and 5 the same, we wanted to treat
|
||||
any number from 1 to 5 the same, we could do:
|
||||
|
||||
```rust
|
||||
let x = 5;
|
||||
|
||||
match x {
|
||||
1 ... 5 => println!("one through five"),
|
||||
_ => println!("anything else"),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `one through five`: 5 is included in the range.
|
||||
|
||||
Ranges are usually used with integers or `char`s:
|
||||
|
||||
```rust
|
||||
let x = 'c';
|
||||
|
||||
match x {
|
||||
'a' ... 'j' => println!("early ASCII letter"),
|
||||
'k' ... 'z' => println!("late ASCII letter"),
|
||||
_ => println!("something else"),
|
||||
}
|
||||
```
|
||||
|
||||
This prints `early ASCII letter`.
|
||||
|
||||
## ref and ref mut
|
||||
|
||||
Usually, when you match against a pattern, bindings are bound by value.
|
||||
This means you'll end up moving the value out:
|
||||
|
||||
```rust,ignore
|
||||
let name = Some(String::from("Bors"));
|
||||
|
||||
match name {
|
||||
// name is moved here because of the binding to the `Some` value.
|
||||
Some(inner_name) => println!("Found a name: {}", inner_name),
|
||||
None => (),
|
||||
}
|
||||
|
||||
// This line will fail to compile:
|
||||
println!("name is: {:?}", name);
|
||||
```
|
||||
|
||||
If you'd prefer to bind `name` by reference, use the `ref` keyword in order to
|
||||
borrow the value instead:
|
||||
|
||||
```rust
|
||||
let name = Some(String::from("Bors"));
|
||||
|
||||
match name {
|
||||
// name is not moved here.
|
||||
Some(ref inner_name) => println!("Found a name: {}", inner_name),
|
||||
None => (),
|
||||
}
|
||||
|
||||
// The match only took a reference to its data rather than moving it.
|
||||
// This works:
|
||||
println!("name is: {:?}", name);
|
||||
```
|
||||
|
||||
And for a mutable reference, use `ref mut`:
|
||||
|
||||
```rust
|
||||
let mut name = Some(String::from("Bors"));
|
||||
|
||||
match name {
|
||||
// name is not moved here.
|
||||
Some(ref mut inner_name) => *inner_name = String::from("Another name"),
|
||||
None => (),
|
||||
}
|
||||
|
||||
// The match only took a reference to its data rather than moving it.
|
||||
// This works and prints the new value we gave it in the match statement:
|
||||
println!("name is: {:?}", name);
|
||||
```
|
||||
|
||||
## Ignoring bindings
|
||||
|
||||
We discussed using `_` as a whole pattern to ignore any value, but you can
|
||||
also use `_` inside of another pattern to ignore just part of a value. This
|
||||
usage of `_` will ignore the inner value of any `Some` value that is not a
|
||||
`Some` with a `6` inside:
|
||||
|
||||
```rust
|
||||
let x = Some(5);
|
||||
|
||||
match x {
|
||||
Some(6) => println!("got a Some(6)"),
|
||||
Some(_) => println!("got a Some and I don't care what's inside"),
|
||||
None => (),
|
||||
}
|
||||
```
|
||||
|
||||
It’s worth noting that using `_` never binds to the value, which means that the
|
||||
value will not be moved:
|
||||
|
||||
```rust
|
||||
let name = Some(String::from("Bors"));
|
||||
|
||||
match name {
|
||||
// name is not moved here because the _ does not bind to the `Some` value.
|
||||
Some(_) => println!("Found a name!"),
|
||||
None => (),
|
||||
}
|
||||
|
||||
// This works:
|
||||
println!("name is: {:?}", name);
|
||||
```
|
||||
|
||||
## Guards
|
||||
|
||||
You can introduce "match guards" with `if`. This adds an extra condition that
|
||||
often uses a value that the pattern has bound to:
|
||||
|
||||
```rust
|
||||
let x = Some(5);
|
||||
|
||||
match x {
|
||||
Some(x) if x < 5 => println!("less than five: {}", x),
|
||||
Some(x) => println!("{}", x),
|
||||
None => (),
|
||||
}
|
||||
```
|
||||
|
||||
In this case, we bound the inner value of a `Some` to `x` and then "guarded" the
|
||||
first match arm with an additional condition that `x` must be less than 5. In
|
||||
this case, `Some(5)` does not have an inner value that is less than 5, so this
|
||||
code will just print out `5`.
|
||||
|
||||
Whew! That’s a lot of different ways to match things. Let's cover one more place
|
||||
you can use your newfound knowledge of patterns: `if let`.
|
Loading…
Reference in New Issue
Block a user