Reputation: 309
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 ""
.
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
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`
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
Upvotes: 2
Views: 1664
Reputation: 36031
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 char
s.
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.
Upvotes: 5