Updating a value in a vector, using other values in the same vector


#1

Hello! I am quite new to rust and stuck trying to do something, that I have a feeling could be straight forward.

Problem:
I have a Vector of Positions (x, y coordinates). I would like to loop over every position, and update it. But to update it I would like to use the other positions from the vector.

The borrow checker won’t allow me to get a reference to a mutable reference (the position I am updating) and an immutable reference the other positions in the vector.

What sound like a good solution to me is: split the vector in one mutable value(the one I am updating), and a vector of immutable values (the other ones).

But I can’t figure out how.

pub struct Point {
    x: usize,
    y: usize,
}

#2

Could you please show that part of code you have written so far?


#3

Yes of course! The function I have trouble getting input for is update_position in this example:

pub struct Point {
    x: usize,
    y: usize,
}
pub struct Entity {
    ... other properties:
    position: Point,
}


pub fn update_position(other_entities: &Vec<Entity>, entity: &mut Entity) {
    if let Some(destination) = find_destination(other_entities, entity) {
        let next_position = find_next_step(&entity.position, &destination);

        entity.position = next_position;
    }
}


fn main() {
    let mut entities: Vec<Entity> = ...
    for e in entities.iter_mut() {
       // here is the issue
       update_position(entities, e); 
    }
}

#4

Using an indexed loop, rather than iterator, can make this simpler. Something like:

for i in 0..entities.len() {
   let destination = find_destination(&entities, &entities[i]);
   if let Some(dest) = destination {
       let next_pos = find_next_step(&entities[i].position, &dest);
       entities[i].position = next_pos;
   }
}

Point is small and cheap enough to copy around. As such, you can employ interior mutability inside Entity for its position field, by putting it inside a Cell. Then you can iterate entities immutably and still be able to mutate their position field.

Finally, if you have a large entity based system, you may want to look at concepts from an ECS, and in particular, the technique of using entity ids/handles to refer to them (instead of references). This may or may not be applicable to you, but worth considering if it may.


#5

Thanks, this is this simple solution I was hoping for. Seems obvious now that I read it.
This is part of the advent of code 2018 challenges. So I was hoping to learn more from it by not using an ECS. But thanks for the tip anyway.