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

Mic*_*tke 3 rust

在学习Rust时,我在正式的Rust书中遇到了以下内容:

模式存在一个缺陷:就像引入新绑定的任何东西一样,它们会引入阴影.例如:

let x = 'x';
let c = 'c';

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

println!("x: {}", x)
Run Code Online (Sandbox Code Playgroud)

这打印:

x: c c: c
x: x
Run Code Online (Sandbox Code Playgroud)

换句话说,x =>匹配模式并引入一个新的绑定,命名x为匹配臂的范围.因为我们已经有一个命名的绑定x,这个新的x阴影它.

我不明白两件事:

  1. 为什么比赛成功?
    不应该有不同的价值cx导致失败吗?
  2. 匹配臂x绑定如何设置'c'
    那是println!表达式的回归吗?

Mat*_* M. 6

关于什么match是一个根本的误解.

模式匹配不是关于值的匹配,而是关于模式的匹配,顾名思义.为了方便和安全,它还允许将名称绑定到匹配模式的内部:

match some_option {
    Some(x) => println!("Some({})", x),
    None    => println!("None"),
}
Run Code Online (Sandbox Code Playgroud)

为方便起见,match被延伸以匹配对具体的匹配时文字(积分或布尔值),我认为在你的困惑的根.

为什么?因为一定match必须详尽无遗!

match表达式在那里,所以编译器可以保证你处理所有可能性; 检查你处理所有模式是很容易的,因为它们在编译器的控制下,检查你是否在存在自定义相等运算符时处理所有值.


在match子句中仅使用名称时,您将创建一个无可辩驳的模式:永远不会失败的模式.在这种情况下,匹配的整个值绑定到此名称.

您可以通过在之后添加第二个匹配子句来展示这一点,编译器将警告后一个绑定无法访问:

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"),
                 ^
Run Code Online (Sandbox Code Playgroud)

结合阴影规则,特别允许通过重用其名称来绑定另一个值来隐藏范围中的绑定,您将获得以下示例:

  • match手臂内,x必然是价值'c'
  • 在手臂之后,唯一x的范围是原始的一个绑定到该值'x'

  • @Shepmaster在[Rust by Example](http://rustbyexample.com/)和其他地方,我见过的所有例子都没有让我失望.另外,我不理解"数据的'形状'这个概念". (2认同)

She*_*ter 5

您的两点是由相同的根本问题引起的。巧合的是,存在此部分的原因是为了指出您要询问的问题!恐怕我基本上会用不同的词来反省这本书的内容。

查看此示例:

match some_variable {
    a_name => {},
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,比赛手臂将永远成功。无论in中的值如何some_variable,它始终将绑定到a_name匹配臂内部的名称。首先要知道这一点很重要-绑定的变量的名称与之外的任何内容都没有关系match

现在转到您的示例:

match c {
    x => println!("x: {} c: {}", x, c),
}
Run Code Online (Sandbox Code Playgroud)

完全相同的逻辑也适用。具有始终匹配的匹配臂,并且不管的值是多少c,它将始终绑定到x该臂内部的名称。

x从外范围('x'在这种情况下)具有在图案匹配无轴承任何。


如果要使用值x来控制模式匹配,则可以使用Match Guard

match c {
    a if a == x => println!("yep"),
    _ => println!("nope"),
}
Run Code Online (Sandbox Code Playgroud)

请注意,在比赛防护(if a == x)中,变量绑定ax返回到可以测试的普通变量的状态。