arn*_*rnm 6 collections iterator immutability rust
我有一个Board(aka &mut Vec<Vec<Cell>>)我想迭代它时更新.我想要更新的新值来自一个函数,它需要一个&Vec<Vec<Cell>>我正在更新的集合.
我尝试了几件事:
使用board.iter_mut().enumerate(),row.iter_mut().enumerate()以便我可以cell在最里面的循环中更新.Rust不允许调用该next_gen函数,因为它需要a,&Vec<Vec<Cell>>并且当您已经有一个可变引用时,您不能拥有不可变引用.
更改next_gen功能签名以接受a &mut Vec<Vec<Cell>>.Rust不允许对对象进行多次可变引用.
我目前正在将所有更新推迟到a HashMap,然后在我执行迭代后应用它们:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法可以让这个代码更新board"就地",也就是说,在最里面的循环中,同时仍然可以next_gen在最里面的循环中调用?
免责声明:
我正在学习Rust,我知道这不是最好的方法.我正在玩,看看我能做什么,不能做什么.我也试图限制任何复制以限制自己一点点.正如oli_obk - ker提到的那样,Conway的生命游戏的这种实现是有缺陷的.
此代码旨在衡量以下几点:
从我在评论中收集到的内容来看,它是可能的std::cell::Cell.但是,使用std:cell:Cell规避了一些核心Rust原则,我在原始问题中将其描述为我的"两难".
有没有办法让这个代码"就地"更新电路板?
存在专门为这些情况制作的类型.巧合地叫它std::cell::Cell.Cell即使多次不可挽回地借用,你也可以改变a的内容.Cell仅限于实现的类型Copy(对于您必须使用的其他类型,RefCell如果涉及多个线程,则必须Arc与somethinng组合使用,例如a Mutex).
use std::cell::Cell;
fn main() {
let board = vec![Cell::new(0), Cell::new(1), Cell::new(2)];
for a in board.iter() {
for b in board.iter() {
a.set(a.get() + b.get());
}
}
println!("{:?}", board);
}
Run Code Online (Sandbox Code Playgroud)
这完全取决于你的next_gen功能.假设除了签名之外我们对该函数一无所知,最简单的方法是使用索引:
fn step(board: &mut Board) {
for row_index in 0..board.len() {
for column_index in 0..board[row_index].len() {
let cell_next = next_gen((row_index, column_index), &board);
if board[row_index][column_index] != cell_next {
board[row_index][column_index] = cell_next;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
有关next_gen不同解决方案的更多信息可能是可能的,但它听起来很像我的细胞自动机,据我所知,这不能在Rust中以迭代器方式完成而不改变类型Board.
您可能担心索引解决方案的效率低于迭代器解决方案,但您应该信任LLVM.如果您的next_gen函数在另一个包中,您应该将其标记为#[inline]LLVM也可以对其进行优化(如果所有内容都在一个包中,则不需要).
不是你的问题的答案,而是你的问题:
由于您正在实施康威的生命游戏,因此您无法就地进行修改.想象一下以下模式:
00000
00100
00100
00100
00000
Run Code Online (Sandbox Code Playgroud)
如果更新第2行,它会1将该行更改为a,0因为它1的邻域中只有两个s.这将导致中间1只看到两个1s而不是那里开始的三个.因此,您始终需要复制整个副本Board,或者像在代码中一样,将所有更改写入其他位置,并在遍历整个板后将其拼接.
| 归档时间: |
|
| 查看次数: |
2198 次 |
| 最近记录: |