简体   繁体   English

Rust书籍的Patterns部分中的匹配阴影示例非常令人困惑

[英]Match shadowing example in the Patterns section of the Rust book is very perplexing

In learning Rust, I encountered the following in the official Rust book : 在学习Rust时,我在正式的Rust书中遇到了以下内容

There's one pitfall with patterns: like anything that introduces a new binding, they introduce shadowing. 模式存在一个缺陷:就像引入新绑定的任何东西一样,它们会引入阴影。 For example: 例如:

 let x = 'x'; let c = 'c'; match c { x => println!("x: {} c: {}", x, c), } println!("x: {}", x) 

This prints: 这打印:

 x: cc: c x: x 

In other words, x => matches the pattern and introduces a new binding named x that's in scope for the match arm. 换句话说, x =>匹配模式并引入一个名为x的新绑定,它位于匹配臂的范围内。 Because we already have a binding named x , this new x shadows it. 因为我们已经有一个名为x的绑定,所以这个新的x影响它。

I don't understand two things: 我不明白两件事:

  1. Why does the match succeed? 为什么比赛成功?
    Shouldn't the differing value of c and x cause this to fail? 不应该cx的不同值导致失败吗?
  2. How does the match arm x binding get set to 'c' ? 匹配臂x绑定如何设置为'c'
    Is that somehow the return of the println! 这是不知何故println!的回归println! expression? 表达?

There is a fundamental misconception of what match is about. 关于match是什么有一个根本的误解。

Pattern-matching is NOT about matching on values but about matching on patterns, as the name imply. 模式匹配不是关于值的匹配,而是关于模式的匹配,顾名思义。 For convenience and safety, it also allows binding names to the innards of the matched pattern: 为了方便和安全,它还允许将名称绑定到匹配模式的内部:

match some_option {
    Some(x) => println!("Some({})", x),
    None    => println!("None"),
}

For convenience, match is extended to match the values when matching specifically against literals (integrals or booleans), which I think is at the root of your confusion. 为了方便起见, match被延伸针对文本 (积分或布尔值),我认为在你的困惑的根特异性匹配时匹配的

Why? 为什么? Because a match must be exhaustive ! 因为match必须是详尽无遗的

match expressions are there so the compiler can guarantee that you handle all possibilities; match表达式是存在的,所以编译器可以保证你处理所有可能性; checking that you handle all patterns is easy because they are under the compiler's control, checking that you handle all values is hard in the presence of custom equality operators. 检查你处理所有模式是很容易的,因为它们在编译器的控制下,检查你是否在存在自定义相等运算符时处理所有值。


When using just a name in the match clause, you create an irrefutable pattern : a pattern that cannot fail, ever. 在match子句中仅使用名称时,您将创建一个无可辩驳的模式 :永远不会失败的模式。 In this case, the entire value being matched is bound to this name. 在这种情况下,匹配的整个值绑定到此名称。

You can exhibit this by adding a second match clause afterward, the compiler will warn that the latter binding is unreachable: 您可以通过在之后添加第二个匹配子句来展示这一点,编译器将警告后一个绑定无法访问:

fn main() {
    let x = 42;
    match x {
        name => println!("{}", name),
        _    => println!("Other"),
    };
}

<anon>:6:5: 6:6 error: unreachable pattern [E0001]
<anon>:6         _    => println!("Other"),
                 ^

Combined with the shadowing rules, which specifically allow hiding a binding in a scope by reusing its name to bind another value, you get the example: 结合阴影规则,特别允许通过重用其名称来绑定另一个值来隐藏作用域中的绑定,您将获得以下示例:

  • within the match arm, x is bound to the value of 'c' match臂内, x绑定到'c'的值
  • after the arm, the only x in scope is the original one bound to the value 'x' 在arm之后,范围中唯一的x是绑定到值'x'的原始'x'

Your two points are caused by the same root problem. 你的两点是由同一根问题引起的。 Coincidentally, the reason that this section exists is to point out the problem you asking about! 巧合的是,这部分存在的原因是指出你问的问题! I'm afraid that I'm basically going to regurgitate what the book says, with different words. 我担心我基本上会用不同的词语反复出现这本书的内容。

Check out this sample: 看看这个样本:

match some_variable {
    a_name => {},
}

In this case, the match arm will always succeed . 在这种情况下,匹配臂将始终成功 Regardless of the value in some_variable , it will always be bound to the name a_name inside that match arm. 无论some_variable中的值some_variable ,它总是绑定到匹配arm中的名称a_name It's important to get this part first — the name of the variable that is bound has no relation to anything outside of the match . 首先获得此部分非常重要 - 绑定变量的名称与match之外的任何内容无关。

Now we turn to your example: 现在我们转向你的例子:

match c {
    x => println!("x: {} c: {}", x, c),
}

The exact same logic applies. 完全相同的逻辑适用。 The match arm with always match, and regardless of the value of c , it will always be bound to the name x inside the arm. 匹配臂始终匹配,并且无论c的值如何,它将始终绑定到手臂内的名称x

The value of x from the outer scope ( 'x' in this case) has no bearing whatsoever in a pattern match. 来自外部范围的x (在这种情况下为'x' )在模式匹配中没有任何影响。


If you wanted to use the value of x to control the pattern match, you can use a match guard : 如果要使用x的值来控制模式匹配,可以使用匹配保护

match c {
    a if a == x => println!("yep"),
    _ => println!("nope"),
}

Note that in the match guard ( if a == x ), the variable bindings a and x go back to acting like normal variables that you can test. 请注意,在匹配保护中( if a == x ),变量绑定ax将返回到可以测试的正常变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM