I have one object that owns another. The owned object has a mutating method that depends on non-mutating methods of its owner. The architecture (simplified as much as possible) looks like this:
struct World {
animals: Vec<Animal>,
}
impl World {
fn feed_all(&mut self) {
for i in 0..self.animals.len() {
self.animals[i].feed(self);
}
}
}
struct Animal {
food: f32,
}
impl Animal {
fn inc_food(&mut self) {
self.food += 1.0;
}
fn feed(&mut self, world: &World) {
// Imagine this is a much more complex calculation, involving many
// queries to world.animals, several loops, and a bunch of if
// statements. In other words, something so complex it can't just
// be moved outside feed() and pass its result in as a pre-computed value.
for other_animal in world.animals.iter() {
self.food += 10.0 / (other_animal.food + self.food);
}
}
}
fn main() {
let mut world = World {
animals: Vec::with_capacity(1),
};
world.animals.push(Animal { food: 0.0 });
world.feed_all();
}
The above does not compile. The compiler says:
error[E0502]: cannot borrow `*self` as immutable because `self.animals` is also borrowed as mutable
--> src/main.rs:8:34
|
8 | self.animals[i].feed(self);
| ------------ ^^^^- mutable borrow ends here
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
I understand why that error occurs, but what is the idiomatic Rust way to do this?
Just to be clear, the example code is not real. It's meant to present the core problem as simply as possible. The real application I'm writing is much more complex and has nothing to do with animals and feeding.
Assume it is not practical to pre-compute the food value before the call to feed()
. In the real app, the method that's analogous to feed()
makes many calls to the World
object and does a lot of complex logic with the results.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…