提交 c1f938d7 编写于 作者: J Jan Likar

Rearrange sections in "Patterns"

  - Move "Destructuring" after "Multiple patterns", because some of
    later sections include examples which make use of destructuring.

  - Move "Ignoring bindings" after "Destructoring", because the former
    features Result<T,E> destructuring. Some of examples in later
    sections use "_" and "..", so "Ignoring bindings" must be
    positioned before them.

  - Fix #27347 by moving "Ref and mut ref" before "Ranges" and
    "Bindings", because "Bindings" section includes a somewhat
    difficult example, which also makes use of "ref" and "mut ref"
    operators.
上级 4b79add0
......@@ -39,79 +39,81 @@ match x {
This prints `one or two`.
# Ranges
# Destructuring
You can match a range of values with `...`:
If you have a compound data type, like a [`struct`][struct], you can destructure it
inside of a pattern:
```rust
let x = 1;
match x {
1 ... 5 => println!("one through five"),
_ => println!("anything"),
struct Point {
x: i32,
y: i32,
}
```
This prints `one through five`.
Ranges are mostly used with integers and `char`s:
```rust
let x = '💅';
let origin = Point { x: 0, y: 0 };
match x {
'a' ... 'j' => println!("early letter"),
'k' ... 'z' => println!("late letter"),
_ => println!("something else"),
match origin {
Point { x, y } => println!("({},{})", x, y),
}
```
This prints `something else`.
# Bindings
[struct]: structs.html
You can bind values to names with `@`:
We can use `:` to give a value a different name.
```rust
let x = 1;
struct Point {
x: i32,
y: i32,
}
match x {
e @ 1 ... 5 => println!("got a range element {}", e),
_ => println!("anything"),
let origin = Point { x: 0, y: 0 };
match origin {
Point { x: x1, y: y1 } => println!("({},{})", x1, y1),
}
```
This prints `got a range element 1`. This is useful when you want to
do a complicated match of part of a data structure:
If we only care about some of the values, we don’t have to give them all names:
```rust
#[derive(Debug)]
struct Person {
name: Option<String>,
struct Point {
x: i32,
y: i32,
}
let name = "Steve".to_string();
let mut x: Option<Person> = Some(Person { name: Some(name) });
match x {
Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
_ => {}
let origin = Point { x: 0, y: 0 };
match origin {
Point { x, .. } => println!("x is {}", x),
}
```
This prints `Some("Steve")`: We’ve bound the inner `name` to `a`.
This prints `x is 0`.
If you use `@` with `|`, you need to make sure the name is bound in each part
of the pattern:
You can do this kind of match on any member, not just the first:
```rust
let x = 5;
struct Point {
x: i32,
y: i32,
}
match x {
e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
_ => println!("anything"),
let origin = Point { x: 0, y: 0 };
match origin {
Point { y, .. } => println!("y is {}", y),
}
```
This prints `y is 0`.
This ‘destructuring’ behavior works on any compound data type, like
[tuples][tuples] or [enums][enums].
[tuples]: primitive-types.html#tuples
[enums]: enums.html
# Ignoring bindings
You can use `_` in a pattern to disregard the type and value.
......@@ -162,154 +164,152 @@ match x {
This prints `Got a tuple!`.
# Guards
# ref and ref mut
You can introduce ‘match guards’ with `if`:
If you want to get a [reference][ref], use the `ref` keyword:
```rust
enum OptionalInt {
Value(i32),
Missing,
}
let x = OptionalInt::Value(5);
let x = 5;
match x {
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
OptionalInt::Value(..) => println!("Got an int!"),
OptionalInt::Missing => println!("No such luck."),
ref r => println!("Got a reference to {}", r),
}
```
This prints `Got an int!`.
This prints `Got a reference to 5`.
If you’re using `if` with multiple patterns, the `if` applies to both sides:
[ref]: references-and-borrowing.html
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
keyword _creates_ a reference, for use in the pattern. If you need a mutable
reference, `ref mut` will work in the same way:
```rust
let x = 4;
let y = false;
let mut x = 5;
match x {
4 | 5 if y => println!("yes"),
_ => println!("no"),
ref mut mr => println!("Got a mutable reference to {}", mr),
}
```
This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
just the `5`, In other words, the the precedence of `if` behaves like this:
# Ranges
```text
(4 | 5) if y => ...
```
You can match a range of values with `...`:
not this:
```rust
let x = 1;
```text
4 | (5 if y) => ...
match x {
1 ... 5 => println!("one through five"),
_ => println!("anything"),
}
```
# ref and ref mut
This prints `one through five`.
If you want to get a [reference][ref], use the `ref` keyword:
Ranges are mostly used with integers and `char`s:
```rust
let x = 5;
let x = '💅';
match x {
ref r => println!("Got a reference to {}", r),
'a' ... 'j' => println!("early letter"),
'k' ... 'z' => println!("late letter"),
_ => println!("something else"),
}
```
This prints `Got a reference to 5`.
This prints `something else`.
[ref]: references-and-borrowing.html
# Bindings
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
keyword _creates_ a reference, for use in the pattern. If you need a mutable
reference, `ref mut` will work in the same way:
You can bind values to names with `@`:
```rust
let mut x = 5;
let x = 1;
match x {
ref mut mr => println!("Got a mutable reference to {}", mr),
e @ 1 ... 5 => println!("got a range element {}", e),
_ => println!("anything"),
}
```
# Destructuring
If you have a compound data type, like a [`struct`][struct], you can destructure it
inside of a pattern:
This prints `got a range element 1`. This is useful when you want to
do a complicated match of part of a data structure:
```rust
struct Point {
x: i32,
y: i32,
#[derive(Debug)]
struct Person {
name: Option<String>,
}
let origin = Point { x: 0, y: 0 };
match origin {
Point { x, y } => println!("({},{})", x, y),
let name = "Steve".to_string();
let mut x: Option<Person> = Some(Person { name: Some(name) });
match x {
Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
_ => {}
}
```
[struct]: structs.html
This prints `Some("Steve")`: We’ve bound the inner `name` to `a`.
We can use `:` to give a value a different name.
If you use `@` with `|`, you need to make sure the name is bound in each part
of the pattern:
```rust
struct Point {
x: i32,
y: i32,
}
let origin = Point { x: 0, y: 0 };
let x = 5;
match origin {
Point { x: x1, y: y1 } => println!("({},{})", x1, y1),
match x {
e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
_ => println!("anything"),
}
```
If we only care about some of the values, we don’t have to give them all names:
# Guards
You can introduce ‘match guards’ with `if`:
```rust
struct Point {
x: i32,
y: i32,
enum OptionalInt {
Value(i32),
Missing,
}
let origin = Point { x: 0, y: 0 };
let x = OptionalInt::Value(5);
match origin {
Point { x, .. } => println!("x is {}", x),
match x {
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
OptionalInt::Value(..) => println!("Got an int!"),
OptionalInt::Missing => println!("No such luck."),
}
```
This prints `x is 0`.
This prints `Got an int!`.
You can do this kind of match on any member, not just the first:
If you’re using `if` with multiple patterns, the `if` applies to both sides:
```rust
struct Point {
x: i32,
y: i32,
}
let origin = Point { x: 0, y: 0 };
let x = 4;
let y = false;
match origin {
Point { y, .. } => println!("y is {}", y),
match x {
4 | 5 if y => println!("yes"),
_ => println!("no"),
}
```
This prints `y is 0`.
This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
just the `5`, In other words, the the precedence of `if` behaves like this:
This ‘destructuring’ behavior works on any compound data type, like
[tuples][tuples] or [enums][enums].
```text
(4 | 5) if y => ...
```
[tuples]: primitive-types.html#tuples
[enums]: enums.html
not this:
```text
4 | (5 if y) => ...
```
# Mix and Match
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册