Assing variables within loop

I have this code:

        let (input, header) = old_header(...);

        loop {
            let (input, header) = parse_header(input)?;

            match header.typ {
                ChunkType::POOL => {
                    let (input, pool_chunk) = parse_pool_header(input)?;
                    println!("string pool chunk: {:?}", string_pool_chunk);
                }
                _ => {
                    println!("unknown type: {}", header.typ);
                    break;
                }
            }
        }

I got bit confused when input variable value stayed same at each loop.

old_header returns for example input value 100, at the start of loop we have call to parse header, it returns 200 for the input, now input variable is 200, let's say it matched the first case and parse_pool_header got called which made the input 300.
Now when we get to the second loop, I expect that input is 300 but it's 100 again.

also getting linting form vscode that input variables from within the match statement is never used.

Is it how it works or I'm making a fatal mi sake?

Yes, you're making a mistake.
Any variable assigned with let is a completely new variable, which no longer exists when outside of the {} block it was created in. This includes the end of a single iteration of a loop. Note that the old variable still exists, it is simply "shadowed" by the new one with the same name.

e.g.

let a = 1;
{
    let a = 2;
    println!("{a}");
}
println!("{a}");

will print

2
1

if you want to modify the values inside your loop, you need to make them mutable, and set them without the let inside your loop.
e.g.

let (mut input, mut header) = old_header(...);
loop {
    (input, header) = parse_header(input)?;
    match header.typ {
        ChunkType::POOL => {
            (input, pool_chunk) = parse_pool_header(input)?;
            println!("string pool chunk: {:?}", string_pool_chunk);
        }
        _ => {
            println!("unknown type: {}", header.typ);
            break;
        }
    }
}
1 Like

You have three let lines in your code which means you have three input variables. Rewrite your code like this and you'll see why it works like it does:

        let (input1, header1) = old_header(...);

        loop {
            let (input2, header2) = parse_header(input1)?;

            match header.typ {
                ChunkType::POOL => {
                    let (input3, pool_chunk) = parse_pool_header(input2)?;
                    println!("string pool chunk: {:?}", string_pool_chunk);
                }
                _ => {
                    println!("unknown type: {}", header2.typ);
                    break;
                }
            }
        }

The rule is simple: every let introduces new variable. It's in reality very convenient, but you have to change your mental model a bit when you hit the issue first time.

1 Like