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

时间:2016-02-22 20:26:04

标签: rust

在学习Rust时,我遇到了以下in the official Rust book

  

模式存在一个陷阱:就像任何引入新模式的东西一样   绑定,他们引入阴影。例如:

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

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

println!("x: {}", x)
     

打印:

x: c c: c
x: x
     

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

我不明白两件事:

  1. 为什么比赛成功?
    cx的不同值不应导致此失败吗?
  2. 匹配臂x绑定如何设置为'c'
    这是以某种方式返回println!表达式吗?

2 个答案:

答案 0 :(得分:5)

match的含义存在根本的误解。

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

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

为方便起见,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"),
                 ^

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

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

答案 1 :(得分:4)

你的两点是由同一根问题引起的。巧合的是,这部分存在的原因是要指出你问的问题!我担心我基本上会用不同的词语反驳这本书所说的内容。

查看此示例:

match some_variable {
    a_name => {},
}

在这种情况下,匹配臂将始终成功。无论some_variable中的值如何,它都将始终绑定到该匹配臂内的名称a_name。首先获得此部分非常重要 - 绑定的变量名称与match之外的任何内容无关。

现在我们转向你的例子:

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

完全相同的逻辑适用。匹配臂始终匹配,无论c的值如何,它都将始终绑定到手臂内的名称x

来自外部作用域x(在这种情况下为'x')在模式匹配中没有任何影响。

如果您想使用x的值来控制模式匹配,可以使用匹配警卫

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

请注意,在匹配守卫(if a == x)中,变量绑定ax会回归到您可以测试的正常变量。