Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run for loop on elements of a vector and change the vector inside the for loop and outside the for loop in rust?

I am new to Rust. I need to create a vector before a for loop. Run for loop on it. Change the vector inside the for loop. Then Change the vector after the for loop.

I tried the following code and tried to use immutable borrow but both did not work.

fn main() {
    let mut vec1 = vec![4, 5];
    vec1.push(6);
    for i in vec1 {
        if i % 2 == 0 {
            vec1.push(7);
        }
    }
    vec1.push(8);
    println!("vec1={:?}", vec1);
}

I expect to compile and change the vector inside and after the for loop. But it shows this error message:

error[E0382]: borrow of moved value: `vec1`
 --> src/main.rs:6:13
  |
2 |     let mut vec1 = vec![4, 5];
  |         -------- move occurs because `vec1` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
3 |     vec1.push(6);
4 |     for i in vec1 {
  |              ----
  |              |
  |              value moved here
  |              help: consider borrowing to avoid moving into the for loop: `&vec1`
5 |         if i % 2 == 0 {
6 |             vec1.push(7);
  |             ^^^^ value borrowed here after move

Can you explain why move occurs? Can you make it compile?

like image 325
Pandharinath Daspute Avatar asked Aug 24 '19 11:08

Pandharinath Daspute


People also ask

HOW DO FOR loops work in Rust?

A for loop's expression in Rust is an iterator that ​returns a series of values. Each element is one iteration of the loop. This value is then bound to variable and can be used inside the loop code to perform operations.

How do I loop a vector in R?

To iterate over items of a vector in R programming, use R For Loop. For every next iteration, we have access to next element inside the for loop block.

Does Rust have for loops?

Rust supports four loop expressions: A loop expression denotes an infinite loop. A while expression loops until a predicate is false. A while let expression tests a pattern.

How do you break a loop in Rust?

The break control statement allows us to stop the execution of a loop, break out of its iteration cycle and continue on to any code after it. To use the break control statement, we simply write the break keyword where we want to break out of the loop.


1 Answers

There are two problems with your code. Luckily, both of them can be solved by changing one thing. The problems are:

  • Writing for _ in vec1 moves the value vec1 into the loop. This is a move like every other move, meaning that the value is not accessible after the loop! If you need a refresher on ownership and moving, please read the related chapter in the Rust book. You can iterating over references to a vector's elements via for _ in &vec1.
  • You are trying to mutate the vector you are iterating over. Regardless of whether you iterate over the vector by value (as you do) or by reference, you cannot change the vector while iterating over it. And there are many good reasons for that! In your case, you could easily end up having an infinite loop if you add elements while iterating.

To solve both problems at the same time, you can iterate over indices to the vector instead of the vectors elements (Playground):

let mut vec1 = vec![4, 5];
vec1.push(6);
for i in 0..vec1.len() {
    if vec1[i] % 2 == 0 {
        vec1.push(7);
    }
}
vec1.push(8);
println!("vec1={:?}", vec1);

This way, the vector is not moved nor borrowed by the for loop and we are free to mutate it during and after the loop. This particular solution iterates over the indices of the original vector, meaning that elements added in the loop are not iterated over by the loop. This is a good protection to avoid accidental infinite loops. Please note, however, that you can still shoot yourself in the foot by, for example, removing elements from the vector during iteration. In general, independent of programming language, mutating collections while iterating over them is dangerous and should only be done with care.

like image 108
Lukas Kalbertodt Avatar answered Oct 29 '22 16:10

Lukas Kalbertodt