A classic moved value problem but im stuck on this

Hello,
im starting with rust cook book but after a long run im stuck on that case... :confused:
any light ?

use test_prog::Settings;
fn main() {
    // part two.
    let mut conf_b: Settings = Settings::new(5);
    conf_b.data = Some("some ascii data");
    conf_b.display_setting();
    let result: Vec<i64> = conf_b
        .zip(Settings::new(5))
        .map(|(x, y)| x * y) //value moved there...
        .skip(1)
        .collect();
    println!("{:?}", result);
    conf_b.display_setting(); //can't do that... 
}
pub mod test_prog {
    pub struct Settings<'a> {
        value: i64,
        iterator_limit: i64,
        itstate: Option<&'a str>,
        pub data: Option<&'a str>,
    }
    impl<'a> Settings<'a> {
        pub fn new(input: i64) -> Settings<'a> {
            Settings {
                value: 0,
                iterator_limit: input,
                itstate: Some("ready"),
                data: None,
            }
        }
        pub fn display_setting(&self) {
            println!(
                "Config state:\nIterator State: {:?},\nData: {:?}",
                self.itstate.unwrap(),
                self.data.unwrap_or("Empty")
            );
        }
    }
    impl<'a> Iterator for Settings<'a> {
        type Item = i64;
        fn next(&mut self) -> Option<Self::Item> {
            if self.value < self.iterator_limit {
                self.value += 1;
                if self.value <= 1 {
                    self.itstate = Some("Iteration in Progress...");
                }
                Some(self.value)
            } else {
                self.itstate = Some("Iteration Done.");
                None
            }
        }
    }
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0382]: borrow of moved value: `conf_b`
  --> src/main.rs:13:5
   |
4  |     let mut conf_b: Settings = Settings::new(5);
   |         ---------- move occurs because `conf_b` has type `Settings<'_>`, which does not implement the `Copy` trait
...
7  |     let result: Vec<i64> = conf_b
   |                            ------ value moved here
...
13 |     conf_b.display_setting();
   |     ^^^^^^ value borrowed here after move

error: aborting due to previous error

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

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

The iterator combinators always consume the iterator they are given. This is why types like Vec<T> don't implement Iterator directly, instead providing an iter method that returns a different type that implements iterator and holds references to the original collection.

If you want to run it without consuming the iterator, you can use the fact that a mutable reference to an iterator is itself an iterator:

let result: Vec<i64> = (&mut conf_b)
    .zip(Settings::new(5))
    .map(|(x, y)| x * y)
    .skip(1)
    .collect();
1 Like

Im stupid ... :grinning:, thanks for your help Alice

You could also use the slightly nicer by_ref()
method instead of explicitly borrowing the iterator.

1 Like

Oh, ok could you right a quick exemple ? that's a very interesting topic for me...

let result: Vec<i64> = conf_b
    .by_ref()
    .zip(Settings::new(5))
    .map(|(x, y)| x * y)
    .skip(1)
    .collect();

It's completely equivalent to my example.

2 Likes

Im going to dig that a little bit further. thanks you so much.