Rust tuple assignment
Destructuring assignments like that are an unstable feature, prone to changes and removal, so you cannot use it in stable rust.
Just use let (x,y) = ...
. "Too many temporary variables" is not a concern you should be worrying about (without profiling, at least), especially since the old x
and y
variables have been moved out of. Let the compiler worry about reusing space; it can do a better job than you can.
Using tuples in nested scopes
At the time of writing, destructuring assignments is still an unstable feature, which means you can not set the x and y tuple values like this:
let x: String;
let y: String;
(x, y) = (String::from("red"), String::from("fire"));
You have to use let (x, y) like this:
let (x, y) = (String::from("red"), String::from("fire"));
However, in some cases you want to declare the tuple in a parent scope (so that you can use it in later code in the same scope), but you want the tuple values to be set in nested scopes - such as if-statements.
In these cases, you cannot use let in the nested scope to refer to the tuple values in the parent scope, because let creates a new tuple in the nested scope - instead of using/referencing the tuple in the parent scope.
However, you can still use let in the nested scopes to create new tuples; and then just bump them up to the parent scope at the end of each nested scope.
fn main() {
let test_value = 1;
// create (x1, y1) in outer scope
let (x1, y1) = {
// create (x2, y2) in first nested scope
let (x2, y2) =
if test_value == 1 {
// create and set (x3, y3) in second nested scope
let x3 = String::from("red");
let y3 = String::from("fire");
(x3, y3) // bump (x3, y3) values to (x2, y2) in first nested scope
}
else {
panic!("Invalid value for test_value");
};
(x2, y2) // bump (x2, y2) values to (x1, y1) in outer scope
};
// Use the (x1, y1) values in the outer scope
println!("x1: {:?} y1: {:?}", x1, y1);
}
In Summary
Code in a nested scope can refer to tuple values created in a parent scope, but it cannot change their values. The parent scope must drag up their values from the nested scope with let and the nested scope must bump the new values to the parent scope - as seen in the above example.
In Summary - This compiles:
let (a1, b1) = (7, 5);
if a1 > b1{
print!("{} is larger than {}", a1, b1);
}
In Summary - This does not compile:
let (a1, b1) = (7, 5);
if a1 > b1{
print!("{} is larger than {}", a1, b1);
(a1, b1) = (10, 8);
}
In Summary - This compiles:
let (a1, b1) = (7, 5);
let (a1, b1) =
if 7 > 5{
println!("{} is larger than {}", a1, b1); // original a1, b1 values
(10, 20) // bump up new values to a1, b1
}
else {
// you need an else statement to make the entire if-statement deterministic,
// otherwise you get expected...found errors
panic!("What?");
};
println!("a1: {:?} b1: {:?}", a1, b1); // new a1, b1 values
Output:
7 is larger than 5
a1: 10 b1: 20
As of Rust version 1.59, this is a stable feature, and your original implementation will work. See here for more information: https://blog.rust-lang.org/2022/02/24/Rust-1.59.0.html#destructuring-assignments.