How do I access a variable outside of an `if let` expression?

后端 未结 3 512
忘掉有多难
忘掉有多难 2020-12-21 15:13

I\'m trying to access command line arguments. If the argument exists, do something, if not, do nothing. I have this code:

fn main() {
    if let Some(a) = st         


        
相关标签:
3条回答
  • 2020-12-21 16:02

    I agree that you should either do whatever you want to do inside the if-else blocks. If you just to not indent your code and your else block is small, you can inverse your if-condition.

    Instead of

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

    you can do this

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

    If you want the variable to be available in the outer scope, but assign it a value in an inner scope, you can declare it outside.

    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
    
    0 讨论(0)
  • 2020-12-21 16:03

    In Rust, it's always useful to ask yourself "what is the type of this variable?". Let's run with your example and pretend it works:

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

    What is the type of b at the println line? Maybe you'd like it to be a boolean, but what is the type if the if clause doesn't pass? There isn't one! In other languages, maybe that would be nil or null, but Rust encodes that information with the Option type - that's where Some and None come from!

    Additionally, scopes are very meaningful in Rust. Items defined inside a scope don't leak outside that scope:

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

    Between the two of these pieces, the code you want to write isn't possible. I agree that the right solution is to embed the println inside the if:

    let arg = Some(true);
    
    if let Some(a) = arg {
        println!("{:?}", a);
    }
    
    0 讨论(0)
  • 2020-12-21 16:09

    For an understanding of what's going on, have a look at the answer by Shepmaster

    I'm not sure what you expect to happen in case the condition is not met. If you just want to abort the program in that case, the idiomatic Rust way is to use unwrap or expect.

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

    If you want a default value in case the argument does not exist, you can use 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);
    

    As a further alternative, you can use the feature that in Rust almost everything is an expression:

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

    The idiomatic Rust way to write that would be with closures and 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);
    
    0 讨论(0)
提交回复
热议问题