Accessing iter within loop based on iter

I would like to use an iterator to build a for loop, but within that loop I need to peek at the next value in the iterator for a comparison.

fn main() {

    let s = "abbcccd";
    let mut iter = s.chars().peekable();
    for chr in iter {
        iter.next();
        println!("current: {}", chr);
        let peek = *iter.peek().unwrap();
        if chr == peek {
            println!("peek: {}", peek);
        }
        println!("next: {}", iter.next().unwrap());
    }
}


(Playground)

Errors:

   Compiling playground v0.0.1 (file:///playground)

error[E0382]: use of moved value: `iter`
 --> src/main.rs:6:5
  |
5 |     for chr in iter {
  |                ---- value moved here
6 |     iter.next();
  |     ^^^^ value used here after move
  |
  = note: move occurs because `iter` has type `std::iter::Peekable<std::str::Chars<'_>>`, which does not implement the `Copy` trait

error[E0382]: use of moved value: `iter`
 --> src/main.rs:8:21
  |
5 |     for chr in iter {
  |                ---- value moved here
...
8 |         let peek = *iter.peek().unwrap();
  |                     ^^^^ value used here after move
  |
  = note: move occurs because `iter` has type `std::iter::Peekable<std::str::Chars<'_>>`, which does not implement the `Copy` trait

error[E0382]: use of moved value: `iter`
  --> src/main.rs:12:30
   |
5  |     for chr in iter {
   |                ---- value moved here
...
12 |         println!("next: {}", iter.next().unwrap());
   |                              ^^^^ value used here after move
   |
   = note: move occurs because `iter` has type `std::iter::Peekable<std::str::Chars<'_>>`, which does not implement the `Copy` trait

warning: variable does not need to be mutable
 --> src/main.rs:2:9
  |
2 |     let mut v: Vec<(usize,char)> = vec![];
  |         ----^
  |         |
  |         help: remove this `mut`
  |
  = note: #[warn(unused_mut)] on by default

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0382`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.

You can replace for chr in iter with while let Some(chr) = iter.next(). Playground.

2 Likes

Not exactly the same situation, but might be interesting as it's another place for while let over for:

http://blog.ssokolow.com/archives/2017/06/23/rust-looping-on-a-member-variable-without-mutably-borrowing-self/

1 Like