Understanding scope and shadowing matches

2020-04-11 10:38发布

I'm trying to improve on the final guessing game sample code a bit. Particularly, I plan to output "Please input a number!" if the user does not input a number rather than "Please input your guess." again. I'm doing this with an inner loop. The code below does work:

let guess: u32;

loop {
    let mut guess_str = String::new();
    io::stdin().read_line(&mut guess_str)
        .ok()
        .expect("Failed to read line");

    guess = match guess_str.trim().parse() {
        Ok(num) => num,
        Err(_) => {
            println!("Please input a number!");
            continue;
        }
    };
    break;
}

I'd like to avoid the guess_str if I can by properly shadowing the matches. If I change guess_str to guess, Rust complains of use of possibly uninitialized variable: `guess`. I'm not sure how the variable could possibly be uninitialized if it's impossible for it to not be uninitialized with the code above. Is there any way to do this only using guess?

标签: rust
1条回答
Fickle 薄情
2楼-- · 2020-04-11 11:39

Let's look at a simpler reproduction:

fn make_guess() -> u32 {
    let guess;

    {
        let mut guess;
        guess = 1;
    }

    guess
}

Here, you create an outer variable guess and then shadow it inside the block. When you assign the value 1 to guess, you are assigning to the inner variable. The outer variable is never set to anything, thus you end up with the "use of possibly uninitialized variable" error.

Is there any way to only use one variable

Indirectly, yes. I'd extract the code to a function. When you have a successful guess, you can simply return. Otherwise you allow the loop to occur:

fn make_guess() -> u32 {
    loop {
        let mut guess = String::new();
        io::stdin().read_line(&mut guess)
            .ok()
            .expect("Failed to read line");

        match guess.trim().parse() {
            Ok(num) => return num,
            Err(_) => {
                println!("Please input a number!");
            }
        }
    }
}

This avoids the shadowing completely, avoids having to use an explicit continue, and adds a small amount of abstraction and organization to your code.

查看更多
登录 后发表回答