在学习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
会影响它。
我不明白两件事:
c
和x
的不同值不应导致此失败吗?x
绑定如何设置为'c'
?println!
表达式吗?答案 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
)中,变量绑定a
和x
会回归到您可以测试的正常变量。