Search code examples
rusttuplesdestructuringmutable

Are variables obtained by destructuring a tuple mutable?


Does destructuring a tuple make the variable mutable?

This is the code snippet that confuses me:

let tup = ("duck", 11, true);

let (_, data, ..) = tup;
println!("data: {}", data);

let (_, .., data) = tup; // I expected that this is not available
println!("data: {}", data);

data = "what"; // like this, but then this one why not?

Solution

  • let actually defines a new variable. So in your code, two data variables exist, one created by the first let, and one created by the second let.

    That said, the second let data shadows the name of the first one, making the first one exist in the background somewhere but being inaccessible because its name has been reused by the second one.

    This is also the reason why you don't need to declare the first data as mut - you never mutate it. It still exists in the background, the new data variable just stole the name.

    The last line fails because data now refers to the second data object, which is a boolean. And you cannot assign strings to booleans. Apart of that, it isn't declared mut, so even if you wrote data = false;, it would fail to compile.

    You can replace the last line with let data = "what";, then it will compile. But then you have three data variables now, with the previous two being shadowed.

    To demonstrate that it is actually shadowed, here is a little example. It temporarily shadows the variable inside of the nested scope; after the scope the previous variable is reachable again because the nested one got dropped:

    fn main() {
        let tup = ("duck", 11, true);
    
        let (_, data, ..) = tup;
        println!("data: {}", data);
    
        {
            let (_, .., data) = tup;
            println!("data: {}", data);
        }
    
        println!("data: {}", data);
    }
    
    data: 11
    data: true
    data: 11