Drekorig
Drekorig

Reputation: 3

Why I can't use the reference to a collection in a for loop?

I learn Rust. For information I am in chapter 3.5 of the Rust book :

https://doc.rust-lang.org/book/ch03-05-control-flow.html

I wrote this code :

fn main() {
let mut a: [i32; 5] = [10, 20, 30, 40, 50];

for (index, value) in a.iter_mut().enumerate() {
    *value /= 10;
    //a[index] -= 1;
    println!("a[{}] : {}", index, value);
}

for index in 0..a.len() {
    a[index] -= 1;
    println!("a[{}] : {}", index, a[index]);
}
a[0] = 10;
println!("Len : {}", a.len());
println!("{:?}", a);
}

I don't undestand why if I uncomment line "//a[index] -= 1;" it generates an error :

error[E0503]: cannot use `a` because it was mutably borrowed
 --> src/main.rs:6:9
  |
4 |     for (index, value) in a.iter_mut().enumerate() {
  |                           ------------------------
  |                           |
  |                           borrow of `a` occurs here
  |                           borrow later used here
5 |         *value /= 10;
6 |         a[index] -= 1;
  |         ^^^^^^^^ use of borrowed `a`

error[E0503]: cannot use `a[_]` because it was mutably borrowed
 --> src/main.rs:6:9
  |
4 |     for (index, value) in a.iter_mut().enumerate() {
  |                           ------------------------
  |                           |
  |                           borrow of `a` occurs here
  |                           borrow later used here
5 |         *value /= 10;
6 |         a[index] -= 1;
  |         ^^^^^^^^^^^^^ use of borrowed `a`

For more information about this error, try `rustc --explain E0503`.
error: could not compile `collections` due to 2 previous errors

What's interesting is that I can access "a[index]" in the loop after.

Upvotes: 0

Views: 97

Answers (1)

Silvio Mayolo
Silvio Mayolo

Reputation: 70257

Iterating involves immutably borrowing. Modifying involves a mutable borrow. You can't have both at the same time. Your second loop isn't iterating over a, it's iterating over a range constructing using (a copy of) a.len(). That range has no actual references to the vector, so you can safely mutably borrow.

Assuming you intend to divide by ten and then subtract one, we can do so with map. Rust is a lot more functional-like in the way it handles iterators, preferring to focus on high-level operations.

let my_new_vec: Vec<_> = a.iter().map(|x| x / 10 - 1).collect();

Upvotes: 1

Related Questions