我正在阅读一些Rust代码,碰到了这一行
if let Some(path) = env::args().nth(1) {
此功能内
fn main() {
if let Some(path) = env::args().nth(1) {
// Try reading the file provided by the path.
let mut file = File::open(path).expect("Failed reading file.");
let mut content = String::new();
file.read_to_string(&mut content);
perform_conversion(content.as_str()).expect("Conversion failed.");
} else {
println!(
"provide a path to a .cue file to be converted into a MusicBrainz compatible tracklist."
)
}
}
该行似乎正在将env
参数分配给变量路径,但是我无法弄清周围的Some()
在做什么。
我看了Option
的文档,了解了在=
的右侧使用时的工作原理,但在左侧却有些困惑。
我认为这行等同于
if let path = Some(env::args().nth(1)) {
答案 0 :(得分:5)
来自reference:
if let表达式在语义上类似于if表达式,但 它期望条件表达式代替条件表达式 通过可重命名的模式,一个=和一个表达式。如果值 =右侧的表达式与模式匹配, 相应的块将执行,否则流程进入 如果存在则跟随else块。就像if表达式,如果让 表达式的值由要评估的块确定。
此处重要的部分是可引用性。在这里,可重复的模式意味着不同的形式。例如:
enum Test {
First(String, i32, usize),
Second(i32, usize),
Third(i32),
}
您可以检查x的值以获得3种不同模式的值,例如:
fn main() {
let x = Test::Second(14, 55);
if let Test::First(a, b, c) = x {}
if let Test::Second(a, b) = x {} //This block will be executed
if let Test::Third(a) = x {}
}
这称为可引用性。但是,请考虑这样的代码:
enum Test {
Second(i32, usize),
}
fn main() {
let x = Test::Second(14, 55);
if let Test::Second(a, b) = x {}
}
由于x的模式很明显,它只有一个模式,因此无法编译。 您可以从reference of refutability获取更多信息。
您也不正确地为此考虑:
if let path = Some(env::args().nth(1)) {
编译器将抛出诸如不可辩驳的if-let模式之类的错误,因为如参考文献所述:“让关键字后跟可辩驳的模式”。在这里,“ let”之后没有可重用的模式。实际上,这段代码试图创建一个名为path的变量,它是一个Option,这是没有意义的,因为不需要“ If ”,
相反,Rust希望您这样写:
let path = Some(env::args().nth(1)); // This will be seem like Some(Some(value))
答案 1 :(得分:1)
其他答案涉及很多细节,可能比您需要知道的还要多。
基本上是这样:
if let Some(path) = env::args().nth(1) {
// Do something with path
} else {
// otherwise do something else
}
与此相同:
match env::args().nth(1) {
Some(path) => { /* Do something with path */ }
_ => { /* otherwise do something else */ }
}
答案 2 :(得分:0)
env::args().nth(1)
返回一个可选值。该值可以为Some(Value)
或None
。
由于您尝试处理Some
情况,因此您写道:
if let Some(value) = my_optional {
// do something with value here.
}
或者,您可以使用match
语句:
match my_optional {
Some(value) => { /* do something with value */ }
None => { }
}
或者您可以使用is_some
和unwrap
检查其中的值来选择变量:
if my_optional.is_some() {
let value = my_optional.unwrap();
// do something with value
}
您也可以选中the if let
documentation。