Search code examples
rustexpressionshadowing

Possible in Rust to perform captures for block expressions?


Simple example of the kind of thing I mean:

let x = 10;
if true {
    let x = 20;
}
println!("x is {}", x);

This will print x is 10, not x is 20, and give me an unused variable warning, because the x in the if block is different than the x outside it. Is there a way I can perform a capture-like operation on the if so that it actually acts on the containing block's x?

I'm imagining here that it's desirable to perform shadowing by repeated let statements, but the example is more concise if it's just an int. In pseudocode, perhaps it would be more like:

let data = get_data_from_user();
let data = initial_processing(data);
let data = further_processing(data);
if some_condition {
    let data = conditional_processing(data);
} else {
    let data = fallback_processing(data);
}

(Perhaps the answer is that this is code smell, and I should move the if some_condition check inside the conditional_processing function call.)

So for instance one possible rewrite of the reproducible example:

let mut x = 10;
if true {
    x = 20;
}

I would consider that to be too divergent from what I'm thinking of doing.

It's possible to write

let x = 10;
let mut y = x;
if true {
    y = 20;
}
let x = y;
println!("x is {}", x);

And so x ends up being a non-mutable variable set to 20, albeit at the cost of introducing a throwaway intermediary mutable variable y. But I'm still curious if it's possible to implement this by letting the if block capture and deliberately shadow a variable outside it.


Solution

  • Updated (see the original answer below)

    You may be interested in

    let data = get_data_from_user();
    let data = initial_processing(data);
    let data = further_processing(data);
    let data = if some_condition {
        conditional_processing(data)
    } else {
        fallback_processing(data)
    };
    

    or if you would like to keep the same value for else

    let x = 10;
    let x = if true {
        20
    } else {
        x
    }
    

    Original answer

    No, it's not possible.

    • You can't force a variable to be visible outside the definition block. So let x = <...> will not work.
    • You can't change value of immutable variable. So x = <...> will not work.
    • There is no other way to assign a value to a variable.