如何访问“if let”表达式之外的变量



我正在尝试访问命令行参数。如果争论存在,就做点什么,如果不存在,就什么都不做。我有这个代码:

fn main() {
    if let Some(a) = std::env::args().nth(2) {
        let b = a;
    }
    println!("{}", a);
}

我无法在此范围之外访问ab

error[E0425]: cannot find value `a` in this scope
 --> src/main.rs:6:20
  |
6 |     println!("{}", a);
  |                    ^ not found in this scope

如何解决此问题?有没有更好的方法来处理我想要做的事情?

要了解发生了什么,请查看Shepmaster 的答案

我不确定如果条件不满足你会发生什么。如果您只想在这种情况下中止程序,那么惯用的Rust方法是使用unwrapexpect

// panics if there are fewer than 3 arguments.
let a = env::args().nth(2).unwrap();
println!("{}", a);

如果要在参数不存在的情况下使用默认值,可以使用unwrap_or

// assigns "I like Rust" to a if there are fewer than 3 arguments
let a = env::args().nth(2).unwrap_or("I like Rust".to_string());
println!("{}", a);

作为另一种选择,您可以使用Rust中几乎所有内容都是表达式的功能:

let b = if let Some(a) = env::args().nth(2) {
    a
} else {
    // compute alternative value
    let val = "some value".to_string();
    // do operations on val
    val
};
println!("{}", b);

Rust惯用的编写方法是使用闭包和unwrap_or_else:

let b = env::args().nth(2).unwrap_or_else(|| {
    // compute alternative value
    let val = "some value".to_string();
    // do operations on val
    val
});
println!("{}", b);

在Rust中,问问自己"这个变量的类型是什么?"总是很有用的。让我们运行您的示例,并假设它有效:

let arg = Some(true);
if let Some(a) = arg {
    let b = a;
}
println!("{:?}", b);

println线上的b是什么类型的?也许您希望它是一个布尔值,但如果if子句不通过,它的类型是什么?没有!在其他语言中,可能是nilnull,但Rust使用Option类型对信息进行编码——这就是SomeNone的来源!

此外,作用域在Rust中非常有意义。范围内定义的项目不会泄漏到该范围外:

{
    let a = 4;
}
println!("{}", a); // NOPE!

在这两部分之间,您想要编写的代码是不可能的。我同意正确的解决方案是将println嵌入if:中

let arg = Some(true);
if let Some(a) = arg {
    println!("{:?}", a);
}

我同意您应该在if-else block s中执行任何您想执行的操作。如果您只是不缩进代码,并且else块很小,那么您可以反转if-condition

代替

let arg = std::env::args().nth(2);
if let Some(a) = arg {
    let b = a;
    // do stuff
} else {
    // do other stuff
}

你可以做这个

let arg = std::env::args().nth(2);
if arg.is_none() {
    // do other stuff
}
let b = arg.unwrap();
// do stuff

如果希望变量在外部作用域中可用,但在内部作用域中为其赋值,则可以在外部声明它。

let arg = std::env::args().nth(2);
let a; // declared but not assigned
if let Some(b) = arg {
    a = b; // wasn't mut but first assignment can be done here
} else {
    a = "Foobar".to_string();
}
println!("{}", a); // available here but was assigned the value inside if

最新更新