I am struggling with variations of this, so say that I have a vectors of tuples and I want to update the first entry of each of them. I found this solution:
let mut v = vec![(0,"a"), (1,"b")];
for &mut (ref mut x, _) in &mut v {
*x += 1;
}
aren't there too many muts? is this idiomatic?
cheers
PS: of course I could write v.iter_mut() rather than &mut v, it's the &mut (ref mut x, _) that annoys me a bit. Is there a way to make it simpler?
I'll correct the misconception in the title, it's not "Marking the iteration variable as a reference", you are using Rust's pattern matching. Any structure you name is deconstructed. Compare the following:
let (x, _) = (1, 2); // deconstruct a tuple, x is just 1
let &y = &5; // deconstruct a reference (= dereference), y is just the number 5.
So it's not just "marking as" but "match this structure and deconstruct it", that is, reach into it and take something out from it.
The pattern matches a mutable reference. And you say that the "contents" of that reference should be bound to the variable ai. The contents is just a number. You dereference the reference to the number this way, and you lose the connection to the original location. If you want to modify the original, you have to modify it through a real reference.
This way: for ai in &mut a { *ai = 2 * (*ai); // because ai is a reference to a number
It looks correct, but it is only concerned with reading the values one by one. Their code is correct but IMO using the word "marking" is not. Anyway, this case is different: we want to write through the reference that came from the iterator, to change the values in the original array or vector.
Ok, although I now understand why this is happening, the more I think about this the more I am convinced it should be corrected. Either we make either one of the following expressions:
for &ai in &a {...}
for &ai in a.iter() {...}
for &mut ai in &mut a {...}
for &mut ai in a.iter_mut() {...}
not acceptable, or we make all work as the programmer would have intended to. Otherwise IMO this notation would anyway be unrecommendable, because if I start with for &ai in &a and then realize halfway that I need mutability I need to go back and change all my code.
This similarly applies to patterns as well, see the rust book patterns section:
If you're matching on a pointer, you can use the same syntax as you declared it with. First, &:
let x = &5;
match x {
&val => println!("Got a value: {}", val),
}
Here, the val inside the match has type i32. In other words, the left-hand side of the pattern destructures the value. If we have &5, then in &val, val would be 5.
[quote="lucatrv, post:18, topic:782"] for &ai in &a
[/quote]destructures the value i.e. moves out of a into ai. Except for Copy types it copies instead. And you can't move out of a reference. And if you move into ai, there's no point assigning to ai for your purpose, you clearly want a reference. So, if you don't want destructuring, don't do this?
Let's play with pattern matching a bit more to see why you don't want this:
fn main() {
let mut a = 0;
match &mut a {
&mut mut x => {
x = 1;
println!("a = {}, x = {}", a, x);
}
}
}
That's a good example, thanks. But I wonder if that would be a good and useful behavior or just misleading for the programmer.
Please notice I'm currently learning Rust, that's why I find so many observations.