在学习Rust时,我在正式的Rust书中遇到了以下内容:
模式存在一个缺陷:就像引入新绑定的任何东西一样,它们会引入阴影.例如:
Run Code Online (Sandbox Code Playgroud)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换句话说,
x =>匹配模式并引入一个新的绑定,命名x为匹配臂的范围.因为我们已经有一个命名的绑定x,这个新的x阴影它.
我不明白两件事:
c并x导致失败吗?x绑定如何设置'c'?println!表达式的回归吗?关于什么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'您的两点是由相同的根本问题引起的。巧合的是,存在此部分的原因是为了指出您要询问的问题!恐怕我基本上会用不同的词来反省这本书的内容。
查看此示例:
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)中,变量绑定a并x返回到可以测试的普通变量的状态。