2

I'm confused how a mutable reference works in a for-loop while an immutable reference does not. Is it an iterator?

I found that after loop, the reference chars refers to value "".

No reference

fn main() {
    let str_value: String = "abc".to_string();

    let chars = str_value.chars();
    for char_value in chars {
        println!("char: {}", char_value);
    }
}
char: a
char: b
char: c

Immutable reference

fn main() {
    let str_value: String = "abc".to_string();

    let chars = str_value.chars();
    for char_value in &chars {
        println!("char: {}", char_value);
    }
}
error[E0277]: `&std::str::Chars<'_>` is not an iterator
 --> src/main.rs:5:23
  |
5 |     for char_value in &chars {
  |                       -^^^^^
  |                       |
  |                       `&std::str::Chars<'_>` is not an iterator
  |                       help: consider removing the leading `&`-reference
  |
  = help: the trait `std::iter::Iterator` is not implemented for `&std::str::Chars<'_>`
  = note: `std::iter::Iterator` is implemented for `&mut std::str::Chars<'_>`, but not for `&std::str::Chars<'_>`
  = note: required by `std::iter::IntoIterator::into_iter`

Mutable reference

fn main() {
    let str_value: String = "abc".to_string();

    let mut chars = str_value.chars();
    for char_value in &mut chars {
        println!("char: {}", char_value);
    }

    // why chars equal ""?
    assert_eq!(chars.as_str(), "");
}
char: a
char: b
char: c
4
  • 1
    "Is it an iterator?" - from the error message: "note: std::iter::Iterator is implemented for &mut std::str::Chars<'_>, but not for &std::str::Chars<'_>", so &mut chars is indeed an iterator. Commented Feb 8, 2020 at 15:20
  • @ForceBru But what's the purpose to make mutable reference be an iterator, and immutable reference can't works.And why after the loop mutable reference refers to empty string. Commented Feb 8, 2020 at 15:35
  • The iterator becomes empty after you iterated over it because there's nothing more to iterate over. It's like if you read a book by ripping out the pages you've read, you won't be able to re-read this book because it'll have no more pages. About the mutable reference, I'm not sure why this is the case. Commented Feb 8, 2020 at 15:38
  • @ForceBru yeah, that's my confusion.When I use a Vector mutable reference in a for-loop, finally the reference seems to be reseted. Commented Feb 8, 2020 at 15:49

1 Answer 1

5

chars is of type Chars which implements ("is a") iterator whose elements are of type char.

In Rust, you can use for-loops on things that implement ("are a") iterator.

Thus, your first example is covered by this: Iterates over chars.

The second example does not work because &chars has type &Chars (a borrowed, immutable reference), which does not implement Iterator.

In the third example, however, you have &mut Chars, and this is an iterator:

impl<I: Iterator + ?Sized> Iterator for &mut I {
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item> { (**self).next() }
    // some details omitted
}

The above says: For any type I that is an Iterator and that may not satisfy ?Sized (all this holds for the type Chars), the type &mut I is an Iterator, whose iterated values are the same as the original iterated types (type Item = I::Item), and that delegates next (and some other methods) to the original iterator.

Thus, the third example sees &mut Chars, knows that Chars is an Iterator, and infers that then &mut Chars is also an Iterator that can be used in a for-loop.

as_str -- according to its documentation (see the example there) gives you the remaining (i.e. not yet iterated) substring, so after the iteration, it should just say "" (i.e. empty), since there is nothing left to be iterated over.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.