Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterable, .iter(&mut self) and mutable borrow from immutable data

Tags:

iterator

rust

fn main() {
    let x = &vec![1,2,3,5,7,11,13,17,19,23,29,31,37,41,47];
    let mut i = x.iter().map(|x|{2*x});

    while let Some(value) = i.next() {
        println!("{}", value);
    }
}

Why does this work?

If I change let mut i = into let i =, I get the error:

  |
3 |     let i = x.iter().map(|x|{2*x});
  |         - help: consider changing this to be mutable: `mut i`
4 | 
5 |     while let Some(value) = i.next() {
  |                             ^^^^^^^^ cannot borrow as mutable

Questions:

  1. Do I really need to borrow as mutable? (Maybe I am missing something here.)
  2. Why do I need to borrow as mutable?
  3. What is really being mutable here? Is it i (the iterable) or value (its values)?
like image 737
Salathiel Genèse Avatar asked Oct 26 '25 02:10

Salathiel Genèse


2 Answers

An iterator in Rust is stateful. .next mutates it in-place to get the next value. Even if the underlying data structure is immutable, the iterator is basically a glorified pointer and is mutable. An immutable iterator is nigh useless: since it can't move across the data structure, it would always be accessing the same element.

Note that you don't need a mutable iterator if you're just passing ownership into something else. So the initial x.iter() doesn't need to explicitly be stored in a mutable location, since its ownership is immediately being passed onto .map. The .map iterator, on the other hand, is mutated by your function, so it needs to be stored in a variable marked as mutable.

  1. Do I really need to borrow as mutable? (Maybe I am missing something here.)

Yes, your code is correct. Though for value in i would be more idiomatic.

  1. Why do I need to borrow as mutable?

Since the iterator is moving (statefully) over the data, it needs to be able to change its own local state to change which element it's pointing to.

  1. What is really being mutable here? Is it i (the iterable) or value (its values)?

The iterator i is mutable. The iterable is x and it is not iterable in your example.

See also my answer on a similar question, which explains the same concept.

like image 114
Silvio Mayolo Avatar answered Oct 28 '25 04:10

Silvio Mayolo


The iterator i must be mutable because it has internal state that updates when next is called. That's how the Iterator trait works.

You can see that Iterator::next mutably borrows self.

trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}
like image 25
Chris Avatar answered Oct 28 '25 04:10

Chris



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!