Deconstruct / assign

Hi!
I have a function that returns a tuple, like this:

fn my_function () -> (i32, i32) {
    (1, 2)
}

If in a piece of code I have a couple of mutable variables, can I assign the function result to both with deconstruction? This doesn't work (it's a useless pseudo-code, of course, just for explaining my request):

let mut x: i32;
let mut y: i32;

for _ in 0..10 {
    (x, y) = my_function();
}

Thanks

This has been disussed before, here is the most recent iteration.

Tldr: this seems unlikely because it would embed the entire expression grammer in the pattern grammer. This seems undesirable.

1 Like

On the other hand, you can use a macro to get the intended behavior.

Here is a PoC (able to reassign to identifiers only):

fn main ()
{
    let (mut x, mut y) = (0, 0);
    dbg!(x);
    dbg!(y);
    reassign!(
        (x, y) = (42, 27)
    );
    dbg!(x + y);
}
1 Like

Thank you! I’ll be studying your code closely :slight_smile:

:grin:

I have made an "improved" version which accepts:

  • nested tuples;

  • new bindings (to be prefixed by let inside the tuple);

  • improved error message when using tuples with too many elements;

  • arbitrary "place expressions" (e.g., var.field, array[index], *(&mut ...) where to perform the assignments;

fn main ()
{
    let mut a = [0, 0];
    reassign! {
        (
            (a[0],),    a[1],   let z,
        ) = (
            (42,),      27,     0,
        )
    }
    dbg!(a.iter().sum::<i32>());
    dbg!(z);
}

I have added (not so many) comments to make the whole macro mess slightly more readable.


The only remaining issue is that there is no type-checking performed on the right hand side of the assignment, so it currently accepts and silently discards extra elements when the tuple on the right is too long.

Here is a version that fixes it:

  • it errors on tuple lengths mismatch
1 Like