К сожалению, вы не можете легко сделать это, компилятор допускает только один изменяемый заем или несколько заимствований одновременно. Даже если вам кажется, что это должно быть законно с точки зрения ржавчины, это не так.
Существует несколько способов исправить это:
- использовать индекс напрямую
- используйте внутреннюю изменчивость
- есть лучшее решение, которое позволит избежать проблемы
В вашем случае я думаю, что использование индекса имеет смысл, потому что вы не хотите иметь текущие планеты в другом pl anet, поэтому мы можем мутировать вектор, чтобы поместить текущий pl anet в конец и создать подрезок из других планет:
#[derive(Debug)]
pub struct Vector2 {
x: f64,
y: f64,
}
#[derive(Debug)]
pub struct Planet {
position: Vector2,
init_velocity: Vector2,
curr_velocity: Vector2,
radius: f64,
mass: f64,
}
impl Planet {
pub fn update_velocity(&mut self, other_planets: &[Planet], grav_constant: f64, timestep: f64) {
println!("{:#?}", other_planets);
}
pub fn update_position(&mut self) {
self.position.x = self.position.x + self.curr_velocity.x;
self.position.y = self.position.y + self.curr_velocity.y;
}
}
struct Guard<'a, T> {
slice: &'a mut [T],
a: usize,
b: usize,
}
impl<'a, T> Guard<'a, T> {
fn new(slice: &'a mut [T], a: usize, b: usize) -> Self {
slice.swap(a, b);
Self { slice, a, b }
}
fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
self.slice.split_last_mut()
}
}
impl<'a, T> Drop for Guard<'a, T> {
fn drop(&mut self) {
self.slice.swap(self.a, self.b);
}
}
fn main() {
let mut planets = Vec::<Planet>::new();
planets.push(Planet {
position: Vector2 { x: 10.0, y: 10.0 },
init_velocity: Vector2 { x: 1.0, y: 1.0 },
curr_velocity: Vector2 { x: 1.0, y: 1.0 },
radius: 20.0,
mass: 500.0,
});
planets.push(Planet {
position: Vector2 { x: 20.0, y: 20.0 },
init_velocity: Vector2 { x: 2.0, y: 2.0 },
curr_velocity: Vector2 { x: 2.0, y: 2.0 },
radius: 40.0,
mass: 1000.0,
});
planets.push(Planet {
position: Vector2 { x: 40.0, y: 40.0 },
init_velocity: Vector2 { x: 4.0, y: 4.0 },
curr_velocity: Vector2 { x: 4.0, y: 4.0 },
radius: 80.0,
mass: 2000.0,
});
let len = planets.len();
let last = len - 1;
for i in 0..len {
let mut g = Guard::new(&mut planets, i, last);
let (p, other_planets) = g.split_last_mut().unwrap(); // can't fail
p.update_velocity(&other_planets, 0.0000000000674 as f64, 0.0);
p.update_position();
}
}
Playground , Guard
существует только для того, чтобы избежать ошибки, ключевой функцией является split_last_mut()
, которая разделит наши планеты на ту, которую мы хотим обработать, и остальные.
См .: