I'm hoping someone can help me with this example because I will use the pattern often.
The sample code at the bottom of this post compiles, runs and produces the desirable output.
The method Bar::store_do_work_restore demonstrates the pattern and I would like to implement using proper rust approaches but I do not know how.
The basic idea of "store_do_work_restore" is that it saves off the member variable foos: Vec<&Foo>, replaces it with the passed in "other: Vec<&Foo>" does some work (represented by the method show()) and then restores the original contents and returns. I would like to improve this code using three single line assignments (shown in the comments) rather than the loops as shown (below each comment).
For example, the commented line:
//let save_foos: Vec<&Foo> = self.foos;
Is my preferred approach however will not compile and produces the following error when "uncommented"
36 | let save_foos: Vec<&Foo> = self.foos;
| ^^^^^^^^^
| |
| move occurs because `self.foos` has type `Vec<&Foo<'_>>`, which does not implement the `Copy` trait
| help: consider borrowing here: `&self.foos`
error: aborting due to previous error
(The suggestion to consider borrowing is of little help btw)
The loop that follows is how I must implement the code since I do not know how to fix this error.
It would be very helpful if someone who knows how to do this would educate me.
When you run the code this is the correct output:
bar(main)=Bar { foos: [Foo { num: 393, name: "Pretzel" }, Foo { num: 23, name: "Theo" }] }
bar(doing work)=Bar { foos: [Foo { num: 23, name: "Theo" }, Foo { num: 2928, name: "Kuno" }, Foo { num: 9393, name: "Birdie" }] }
bar(main)=Bar { foos: [Foo { num: 393, name: "Pretzel" }, Foo { num: 23, name: "Theo" }] }
The basic idea is that the "doing_work" line shows the temporary vector that has been copied in using loops, but I would prefer the code to use single line assignments.
Here's the sample code:
#[derive(Debug)]
struct Foo<'a> {
num: i32,
name: &'a str,
}
static FOOS: [Foo; 4] = [
Foo{
num: 23,
name: "Theo",
},
Foo{
num: 2928,
name: "Kuno",
},
Foo{
num: 393,
name: "Pretzel",
},
Foo{
num: 9393,
name: "Birdie",
},
];
#[derive(Debug)]
struct Bar<'a> {
foos: Vec<&'a Foo<'a>>,
}
impl <'a> Bar <'a> {
fn show(&self, label: &str) {
println!("bar({})={:?}", label, self);
}
fn store_do_work_restore<'b>(&mut self, other: &'a Vec<&Foo>) {
//let save_foos: Vec<&Foo> = self.foos;
// above gives compiler error about Copy trait
// this block does the work I want instead
let mut save_foos: Vec<&Foo> = Vec::new();
for foo in self.foos.iter() {
save_foos.push(foo);
}
//self.foos = *other;
// Same issue here
self.foos.clear();
for foo in other.iter() {
self.foos.push(foo);
}
self.show("doing work");
//self.foos = save_foos;
// same issue here.
self.foos.clear();
for foo in save_foos.iter() {
self.foos.push(foo);
}
}
}
fn main() {
let mut bar = Bar {
foos: vec![&FOOS[2], &FOOS[0]],
};
bar.show("main");
let other = &vec![&FOOS[0], &FOOS[1], &FOOS[3]];
bar.store_do_work_restore(other);
bar.show("main");
}