trait OnUpdate {
fn on_update(&mut self, x: &i32);
}
struct Foo {
field: i32,
cbs: Vec<Box<OnUpdate>>,
}
struct Bar {
foos: Vec<Foo>,
}
impl Bar {
fn call_foo_cb(&mut self) {
self.foos
.iter_mut()
.for_each(|foo| foo.cbs.iter_mut().for_each(|cb| cb.on_update(&self.value(*foo)))) // compile error see below
// .for_each(|foo| foo.cbs.iter_mut().for_each(|cb| cb.on_update(&10))) // works
}
fn value(&self, foo: Foo) -> i32 {
foo.field + self.foos.len() as i32 // pretend some calculation based on the current foo and self
}
}
The above code is to demonstrate my problem. I am new to rust and I am wondering what is the best way to refactor in idiomatic rust way.
Thanks in advance.
--> src/lib.rs:348:23
|
346 | self.foos
| --------- mutable borrow occurs here
347 | .iter_mut()
348 | .for_each(|foo| foo.cbs.iter_mut().for_each(|cb| cb.on_update(&self.value(*foo))))
| -------- ^^^^^ immutable borrow occurs here ---- second borrow occurs due to use of `self` in closure
| |
| mutable borrow later used by call
Its easier for me to reason about this with for loops, so consider this equivalent:
for foo in &mut self.foos {
for cb in &mut foo.cbs {
cb.on_update(&self.value(foo));
}
}
If the calculated value doesn't depend on cb
, then it can be moved out of the loop:
for foo in &mut self.foos {
let x = self.value(foo);
for cb in &mut foo.cbs {
cb.on_update(&x);
}
}
And then, you can change out the mutable loop for one using indexes to avoid creating a mutable borrow until later:
for i in 0..self.foos.len() {
let x = self.value(&self.foos[i]);
for cb in &mut self.foos[i].cbs {
cb.on_update(&x);
}
}
This code assumes that the value
function actually takes the Foo
by reference since its not Copy
or Clone
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.