💻博主现有专栏:
C51单片机(STC89C516),c语言,c++,离散数学,算法设计与分析,数据结构,Python,Java基础,MySQL,linux,基于HTML5的网页设计及应用,Rust(官方文档重点总结),jQuery,前端vue.js,Javaweb开发,Python机器学习等
🥏主页链接:
模式有两种形式:refutable(可反驳的)和 irrefutable(不可反驳的)。能匹配任何传递的可能值的模式被称为是 不可反驳的(irrefutable)。一个例子就是
let x = 5;
语句中的x
,因为x
可以匹配任何值所以不可能会失败。对某些可能的值进行匹配会失败的模式被称为是 可反驳的(refutable)。一个这样的例子便是if let Some(x) = a_value
表达式中的Some(x)
;如果变量a_value
中的值是None
而不是Some
,那么Some(x)
模式不能匹配。函数参数、
let
语句和for
循环只能接受不可反驳的模式,因为当值不匹配时,程序无法进行有意义的操作。if let
和while let
表达式可以接受可反驳和不可反驳的模式,但编译器会对不可反驳的模式发出警告,因为根据定义它们旨在处理可能的失败:条件表达式的功能在于它能够根据成功或失败来执行不同的操作。通常我们无需担心可反驳和不可反驳模式的区别,不过确实需要熟悉可反驳性的概念,这样当在错误信息中看到时就知道如何应对。遇到这些情况,根据代码行为的意图,需要修改模式或者使用模式的结构。
let Some(x) = some_option_value;
如果
some_option_value
的值是None
,其不会成功匹配模式Some(x)
,表明这个模式是可反驳的。然而,因为let
对于None
匹配不能产生任何合法的代码,所以let
语句只能接受不可反驳模式。Rust 会在编译时抱怨我们尝试在要求不可反驳模式的地方使用可反驳模式:$ cargo run Compiling patterns v0.1.0 (file:///projects/patterns) error[E0005]: refutable pattern in local binding: `None` not covered --> src/main.rs:3:9 | 3 | let Some(x) = some_option_value; | ^^^^^^^ pattern `None` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `Option<i32>` defined here = note: the matched value is of type `Option<i32>` help: you might want to use `if let` to ignore the variant that isn't matched | 3 | let x = if let Some(x) = some_option_value { x } else { todo!() }; | ++++++++++ ++++++++++++++++++++++ For more information about this error, try `rustc --explain E0005`. error: could not compile `patterns` due to previous error
因为我们没有覆盖(也不可能覆盖!)到模式
Some(x)
的每一个可能的值,所以 Rust 会合理地抗议。为了修复在需要不可反驳模式的地方使用可反驳模式的情况,可以修改使用模式的代码:不同于使用
let
,可以使用if let
。如此,如果模式不匹配,大括号中的代码将被忽略,其余代码保持有效。if let Some(x) = some_option_value { println!("{}", x); }
我们给了代码一个得以继续的出路!虽然我们没办法在避免产生错误的情况下使用不可反驳模式,但这段使用可反驳模式的代码是完全有效的。
if let x = 5 { println!("{}", x); };
$ cargo run Compiling patterns v0.1.0 (file:///projects/patterns) warning: irrefutable `if let` pattern --> src/main.rs:2:8 | 2 | if let x = 5 { | ^^^^^^^^^ | = note: `#[warn(irrefutable_let_patterns)]` on by default = note: this pattern will always match, so the `if let` is useless = help: consider replacing the `if let` with a `let` warning: `patterns` (bin "patterns") generated 1 warning Finished dev [unoptimized + debuginfo] target(s) in 0.39s Running `target/debug/patterns` 5
基于此,
match
匹配分支必须使用可反驳模式,除了最后一个分支需要使用能匹配任何剩余值的不可反驳模式。Rust 允许我们在只有一个匹配分支的match
中使用不可反驳模式,不过这么做不是特别有用,并可以被更简单的let
语句替代。