Add `with mut` syntax to mutate variable in place

IMHO as Rust we sometimes need to mutate variable it will be nice to have syntax like this:

let vec = Vec::new();

with mut vec {
    vec.push(1);
    vec.push(2);
}

println!("{:?}", vec);

It will be the same as:

let vec = Vec::new();

let mut vec = vec;
vec.push(1);
vec.push(2);
let vec = vec;

println!("{:?}", vec);

This syntax will allow to visually mark code that will mutate variable.

What about

let vec = {
    let mut vec = Vec::new();
    vec.push(1);
    vec.push(2);
    vec
};
7 Likes

This involves adding a new keyword, which I am against (unless its already reserved?), and +1 to @stebalien’s comment, thats a much better and more orthogonal way to do it. We dont need to add functionality that mirrors something else at the moment.

Is there a good place to put this technique in the documentation? Or a place where techniques and good practices like this can be gathered in general?

Note that the current syntax is very close to what you are proposing:

let vec = Vec::new();
{
    let mut vec = vec;
    vec.push(1);
    vec.push(2);
}
println!("{}", vec);

This does not scale very well for many mutable variables, see the var macro for that.

You’re moving the vec into a scope and dropping it, though.

Ugh. It’d be nice to cut down on macros such as var!. It makes no real sense and confuses people (e.g. myself).

You are right, my code does not work because println uses a dropped vec. Sorry about that, I should have tested it before posting.

I don't think it can be fixed, but it should be possible to write a macro, something like

with_mut! vec {
    vec.push(1);
    vec.push(2);
}

(Not sure whether this syntax is possible with the current macro rules though.)

I would really like to write let mut (a, b, c) instead of let (mut a, mut b, mut c).

This works:

macro_rules! with_mut {
    ($($v:ident),+ in $e:expr) => {
        let ($($v,)+) = {
            let ($(mut $v,)+) = ($($v,)+);
            $e;
            ($($v,)+)
        }
    }
}

fn main() {
    let a = 0;
    let b = 0;
    with_mut!(a, b in {
        a = 1;
        b = 2;
    });
    println!("{}, {}", a, b);
}

Why? The gain in number of symbols is small and the loss in readability for people not intimately familiar with your code is huge. Additionally, imagine that you have a bug in your macros (perhaps, someone accidentally writes let mut (a, mut b, c)) - how easy would it be to debug your code?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.