I want to loop over a fixed set of variables, and initialise each one according to the output of an iterator.
In my example, the input string 'dimensions' represents package dimensions, in the form e.g. "32x13x16". I am splitting on 'x' to get length, width, and height. I know there will always be exactly three dimensions in the input. I make a list of my three variables and I assign them to the three outputs of my iterator & parser.
let mut l: u32 = 0;
let mut w: u32 = 0;
let mut h: u32 = 0;
let mut dimensions = dimensions.split("x");
for dim in [&mut l, &mut w, &mut h].iter_mut() {
match dimensions.next() {
Some(x) => {
let num: u32 = x.parse().expect("dimensions should be integers");
**dim = num
}
None => break,
}
}
My code works, but it seems over-complicated to me. I have to double-deference the variable in order to assign it. I cannot find a way to declare the variables or the loop such that there is only one layer of dereferencing, which the compiler will accept. Shouldn't I be able to write it in a way where it's just one level of reference?
Also, the compiler requires me to assign initial values to my l, w, and h variables before I use them, but I am going to overwrite them immediately. If I do not initialise my variables, the compiler errors. Is there a way I can avoid this?
In general is there a more idiomatic way I can achieve this?
My code works, but it seems over-complicated to me. I have to double-deference the variable in order to assign it - shouldn't I be able to write it in a way where it's just one level of reference?
You only need iter_mut
to get mutable references to the contents of an iterator. In your case the iterator already contains mutable references, so no need to get &mut &mut T
.
for dim in [&mut l, &mut w, &mut h] {
match dimensions.next() {
Some(x) => {
let num: u32 = x.parse().expect("dimensions should be integers");
*dim = num
}
None => break,
}
}
Also, the compiler requires me to assign initial values to my l, w, and h variables before I use them, but I am going to overwrite them immediately - is there a way I can avoid this?
If you cannot statically prove that every variable will have been assigned — which you can't, because you can't ensure that dimensions
has at least three components — then Rust will correctly assume the variables might be unassigned.
However, you can do something like this:
let [l, w, h] = [(); 3].map(|_| {
dimensions
.next()
.and_then(|s| s.parse::<u32>().ok())
.expect("dimensions should be integers")
});