如何访问`if let`表达式之外的变量?

时间:2015-03-23 14:46:35

标签: rust

我试图访问命令行参数。如果论证存在,做一些事情,如果没有,什么都不做。我有这段代码:

if let Some(a) = env::args().nth(2) {
  let b = a;
}

println!("{}", a) // error: unresolved name 'a' (same with 'b')

但是,我无法访问此范围之外的var a或b。我该如何解决这个问题?

或者,有没有更好的方法来接近我尝试做的事情?

3 个答案:

答案 0 :(得分:5)

在Rust中,问自己“这个变量的类型是什么?”总是有用的。让我们用你的例子运行并假装它有效:

let arg = Some(true);

if let Some(a) = arg {
    let b = a;
}

println!("{:?}", b);

b行的println类型是什么?也许你希望它是一个布尔值,但如果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);
}

答案 1 :(得分:4)

要了解正在发生的事情,请查看@Shepmaster

的答案

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

// 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);

正如@Shepmaster所提到的那样,写出的ido Rust方法就是封闭:

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);

答案 2 :(得分:0)

我同意您应该在if-else block内做任何您想做的事情。如果只是不缩进代码而您的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