Some()在变量赋值的左侧做什么?

时间:2018-12-23 05:57:29

标签: syntax rust pattern-matching

我正在阅读一些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)) {

3 个答案:

答案 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_someunwrap检查其中的值来选择变量:

if my_optional.is_some() {
    let value = my_optional.unwrap();
    // do something with value
}

您也可以选中the if let documentation