Nikos Iliakis
Nikos Iliakis

Reputation: 167

Mutate running variable in loop Rust

I have a for loop in Rust and in a condition that is satisfied I want to rerun a part of the loop. For example:

for mut n in 0..vector.len(){
...
   if condition {
      n = 3;
  }
}

But in the next iteration n is not 3 and the loop continues. Any ideas?

Upvotes: 4

Views: 1919

Answers (1)

user4815162342
user4815162342

Reputation: 154836

for n in 0..x assigns to n values from 0 up to (but excluding) x without taking into account mutations to n, if they occur. That's the case in other languages with foreach-style iteration, e.g. in Python with for n in range(len(vector)), or in C++20 with for (auto n: std::views::iota(0, vector.size())).

If you need to occasionally return to a previous state, as afforded by C's for (n = 0; n < x; n++), the simplest option is to just code the C-style loop:

let mut n = 0;
while n < vector.len() {
    ...
    if condition {
        n = 3;
        continue;
    }
    n += 1;
}

The downside is that n += 1 is buried at the end of the loop, so that a continue that just wants to keep looping (without resetting the loop counter) would actually fail to increment n. If that bothers you (and it'd bother me), you can switch to a slightly different foreach-based implementation, where the range is explicit. Instead of with for, you loop over the range with while let. That gives you the robustness of foreach while allowing you to modify the range you're looping over from inside the loop:

let mut range = 0..vector.len();
while let Some(n) = range.next() {
    ...
    if condition {
        range = 3..vector.len();
    }
}

Note that your original code evaluated vector.len() only once. The C-style loop checks it every time, and this last example also checks it when condition is true. If you change the size of the vector, you should probably accompany vector.push(...) by range = n..vector.len() to correct the upper bound.

Upvotes: 6

Related Questions