I have a Board (a.k.a. &mut Vec<Vec<Cell>>) which I would like to update while iterating over it. The new value I want to update with is derived from a function which requires a &Vec<Vec<Cell>> to the collection I'm updating.
I have tried several things:
Use
board.iter_mut().enumerate()androw.iter_mut().enumerate()so that I could update thecellin the innermost loop. Rust does not allow calling thenext_genfunction because it requires a&Vec<Vec<Cell>>and you cannot have a immutable reference when you already have a mutable reference.Change the
next_genfunction signature to accept a&mut Vec<Vec<Cell>>. Rust does not allow multiple mutable references to an object.
I'm currently deferring all the updates to a HashMap and then applying them after I've performed my iteration:
fn step(board: &mut Board) {
let mut cells_to_update: HashMap<(usize, usize), Cell> = HashMap::new();
for (row_index, row) in board.iter().enumerate() {
for (column_index, cell) in row.iter().enumerate() {
let cell_next = next_gen((row_index, column_index), &board);
if *cell != cell_next {
cells_to_update.insert((row_index, column_index), cell_next);
}
}
}
println!("To Update: {:?}", cells_to_update);
for ((row_index, column_index), cell) in cells_to_update {
board[row_index][column_index] = cell;
}
}
Is there a way that I could make this code update the board "in place", that is, inside the innermost loop while still being able to call next_gen inside the innermost loop?
Disclaimer:
I'm learning Rust and I know this is not the best way to do this. I'm playing around to see what I can and cannot do. I'm also trying to limit any copying to restrict myself a little bit. As oli_obk - ker mentions, this implementation for Conway's Game of Life is flawed.
This code was intended to gauge a couple of things:
- if this is even possible
- if it is idiomatic Rust
From what I have gathered in the comments, it is possible with std::cell::Cell. However, using std:cell:Cell circumvents some of the core Rust principles, which I described as my "dilemma" in the original question.
There exists a type specially made for situations such as these. It's coincidentally called
std::cell::Cell. You're allowed to mutate the contents of aCelleven when it has been immutably borrowed multiple times.Cellis limited to types that implementCopy(for others you have to useRefCell, and if multiple threads are involved then you must use anArcin combination with somethinng like aMutex).