Update ch18-03-pattern-syntax.md

This commit is contained in:
Zheng Ping 2017-06-27 18:06:09 +08:00 committed by GitHub
parent 4bb6a2dc43
commit a451a0e824

View File

@ -282,12 +282,9 @@ fn main() {
<span class="caption">例18-18: 为了消除对未被使用变量的警告以一个下划线开始来命名变量</span>
Note that there is a subtle difference between using only `_` and using a name
that starts with an underscore like `_x`: `_x` still binds the value to the
variable, but `_` doesn't bind at all.
注意, 只使用`_`和使用一个以一个下划线起头的名字是有微妙的不同的: `_x`仍然会把值绑定到变量上但是`_`不会绑定值.
Listing 18-19 shows a case where this distinction matters: `s` will still be
moved into `_s`, which prevents us from using `s` again:
例18-19显示了这种区别的主要地方: `s`将仍然被转移到`_s`, 它会阻止我们继续使用`s`:
```rust,ignore
let s = Some(String::from("Hello!"));
@ -299,11 +296,9 @@ if let Some(_s) = s {
println!("{:?}", s);
```
<span class="caption">Listing 18-19: An unused variable starting with an
underscore still binds the value, which may take ownership of the value</span>
<span class="caption">例18-19: 以下划线起头的未被使用的变量仍然会绑定值, 它也会拥有值的所有权</span>
Using underscore by itself, however, doesn't ever bind to the value. Listing
18-20 will compile without any errors since `s` does not get moved into `_`:
只使用下划线本身却不会绑定值. 例18-20在编译时将不会报错, 因为`s`不会被转移到`_`:
```rust
let s = Some(String::from("Hello!"));
@ -315,20 +310,14 @@ if let Some(_) = s {
println!("{:?}", s);
```
<span class="caption">Listing 18-20: Using underscore does not bind the
value</span>
<span class="caption">例18-20: 使用下划线不会绑定值</span>
This works just fine. Because we never bind `s` to anything, it's not moved.
上面的代码能很好的运行. 因为我们没有把`s`绑定到其它地方, 它没有被转移.
#### Ignoring Remaining Parts of a Value with `..`
#### 用`..`忽略剩余的值
With values that have many parts, we can extract only a few parts and avoid
having to list underscores for each remaining part by instead using `..`. The
`..` pattern will ignore any parts of a value that we haven't explicitly
matched in the rest of the pattern. In Listing 18-21, we have a `Point` struct
that holds a coordinate in three dimensional space. In the `match` expression,
we only want to operate on the `x` coordinate and ignore the values in the `y`
and `z` fields:
对于有多个字段的值而言, 我们可以只提取少数字段并使用`..`来代替下划线, 这就避免了用`_`把剩余的部分列出来的麻烦. `..`模式将忽略值中没有被精确匹配值中的其它部分. 在例18-21中, 我们有一个持有三维空间坐标的`Point`结构. 在`match`表达式里,
我们只想操作`x`坐标上的值并忽略`y`坐标和`z`坐标上的值:
```rust
struct Point {
@ -344,15 +333,11 @@ match origin {
}
```
<span class="caption">Listing 18-21: Ignoring all fields of a `Point` except
for `x` by using `..`</span>
<span class="caption">例18-21: 通过用`..`来忽略除了`x`以外的所有其它`Point`的字段</span>
Using `..` is shorter to type than having to list out `y: _` and `z: _`. The
`..` pattern is especially useful when working with structs that have lots of
fields in situations where only one or two fields are relevant.
使用`..`比列出`y: _`和`z: _`写起来更简单. 当一个结构有很多字段但却只需要使用少量字段时`..`模式就特别有用.
`..` will expand to as many values as it needs to be. Listing 18-22 shows a use
of `..` with a tuple:
`..`将会囊括它能匹配的尽可能多的值. 例18-22显示了一个在元组中使用`..`的情况:
```rust
fn main() {
@ -366,15 +351,11 @@ fn main() {
}
```
<span class="caption">Listing 18-22: Matching only the first and last values in
a tuple and ignoring all other values with `..`</span>
<span class="caption">例18-22: 用`..`匹配元组中的第一和最后一个值并忽略掉所有的其它值</span>
Here, we have the first and last value matched, with `first` and `last`. The
`..` will match and ignore all of the things in the middle.
我们在这里用`first`和`last`来匹配了第一和最后一个值. `..`将匹配并忽略中间的所有其它值.
Using `..` must be unambiguous, however. Listing 18-23 shows an example where
it's not clear to Rust which values we want to match and which values we want
to ignore:
然而使用`..`必须清晰明了. 例18-23中的代码就不是很清晰, Rust看不出哪些值时我们想匹配的, 也看不出哪些值是我们想忽略的:
```rust,ignore
fn main() {
@ -388,10 +369,9 @@ fn main() {
}
```
<span class="caption">Listing 18-23: An attempt to use `..` in a way that is
ambiguous</span>
<span class="caption">例18-23: 尝试含混不清地使用`..`</span>
If we compile this example, we get this error:
如果我们编译上面的例子, 我们会得到下面的错误:
```text
error: `..` can only be used once per tuple or tuple struct pattern
@ -401,20 +381,11 @@ error: `..` can only be used once per tuple or tuple struct pattern
| ^^
```
It's not possible to determine how many values in the tuple should be ignored
before one value is matched with `second`, and then how many further values are
ignored after that. We could mean that we want to ignore 2, bind `second` to 4,
then ignore 8, 16, and 32, or we could mean that we want to ignore 2 and 4,
bind `second` to 8, then ignore 16 and 32, and so forth. The variable name
`second` doesn't mean anything special to Rust, so we get a compiler error
since using `..` in two places like this is ambiguous.
上面的代码中在一个值被匹配到`second`之前不可能知道元组中有多少值应该被忽略, 同样在`second`被匹配后也不知道应该有多少值被忽略. 我们可以忽略2, 把`second`绑定到4, 然后忽略8、16和32, 或者我们也可以忽略2和4, 把`second`绑定到8, 然后再忽略16和32. 对Rust而言, 变量名`second`并不意味着某个确定的值, 因为像这样在两个地方使用`..`是含混不清的, 所以我们就得到了一个编译错误.
### `ref` and `ref mut` to Create References in Patterns
### 用`ref`和`ref mut`在模式中创建引用
Usually, when you match against a pattern, the variables that the pattern
introduces are bound to a value. This means you'll end up moving the value into
the `match` (or wherever you're using the pattern) since the ownership rules
apply. Listing 18-24 shows an example:
当你匹配一个模式时, 模式匹配的变量会被绑定到一个值. 也就是说你会把值转移进`match`(或者是其它你使用了模式的地方), 这是所有权规则的作用. 例18-24提供了一个例子:
```rust,ignore
let robot_name = Some(String::from("Bors"));
@ -427,8 +398,7 @@ match robot_name {
println!("robot_name is: {:?}", robot_name);
```
<span class="caption">Listing 18-24: Creating a variable in a match arm pattern
takes ownership of the value</span>
<span class="caption">例18-24: 在一个匹配分支模式里创建的变量会拥有值的所有权</span>
This example will fail to compile since the value inside the `Some` value in
`robot_name` is moved within the `match` when `name` binds to that value.