[英]How can I match without borrowing in Rust?
I'm wrestling with the borrow checker while trying to write Conway's Game of Life. 在尝试撰写康威的生命游戏时,我正在与借阅检查员搏斗。 I have two for loops doing a mutable borrow on
self.cell_states
, which is a Vec<Vec<CellState>>
( CellState
is an enum) so that I can update the Alive
or Dead
status of each cell. 我有两个for循环在
self.cell_states
上进行可变借用,这是一个Vec<Vec<CellState>>
( CellState
是一个枚举),这样我就可以更新每个单元格的Alive
或Dead
状态。
In order to decide if a cell should be alive or dead though, it needs to see how many of the surrounding cells are alive. 为了确定一个细胞是否应该存活或死亡,它需要看到有多少周围细胞存活。 This is where I've run into problems.
这是我遇到问题的地方。 The only way I can find to check if a cell is alive is to do a
match
statement, but apparently match
borrows the value, which is not allowed, since I've already done a mutable borrow. 我可以找到检查单元格是否存活的唯一方法是执行
match
语句,但显然match
借用了值,这是不允许的,因为我已经完成了可变的借位。 It seems to me that I could just copy the value and check against the copied value, so I tried match self.cell_states[i+x-1][j+y-1].clone() {...}
, but to no avail. 在我看来,我可以复制值并检查复制的值,所以我尝试
match self.cell_states[i+x-1][j+y-1].clone() {...}
,但无济于事。 How can I do a match without borrowing? 如何在不借用的情况下进行比赛?
error[E0502]: cannot borrow `cell_states` as immutable because it is also borrowed as mutable
--> src/main.rs:18:27
|
11 | for (i, row) in cell_states.iter_mut().enumerate() {
| ----------------------------------
| |
| mutable borrow occurs here
| mutable borrow used here, in later iteration of loop
...
18 | match cell_states[i+x-1][j+y-1] {
| ^^^^^^^^^^^ immutable borrow occurs here
My code is as follows ( Playground ): 我的代码如下( 游乐场 ):
#[derive(Copy, Clone)]
pub enum CellState {
Dead,
Alive
}
fn main() {
let mut cell_states = vec![vec![CellState::Dead; 10]; 10];
for (i, row) in cell_states.iter_mut().enumerate() {
for (j, cell) in row.iter_mut().enumerate() {
// Count the living cells around cell
let mut count = 0;
for x in 0..3 {
for y in 0..3 {
match cell_states[i+x-1][j+y-1] {
CellState::Alive => count += 1,
_ => ()
}
}
}
}
}
}
How can I match without borrowing in Rust?
如果不借用Rust,我该怎么匹配?
You can't. 你不能。
Every time you access a variable, you are borrowing it. 每次访问变量时,都要借用它。 Printing a variable?
打印变量? That's borrowing.
这是借来的。 Checking if the variable has a specific value?
检查变量是否具有特定值? Borrowing again.
再借一次。 Copying the value of a variable?
复制变量的值? Also borrowing.
也借。
You are trying to access values of the vector while the vector is mutably borrowed. 您正试图在向量可变地借用时访问向量的值。 This just won't work -- the borrow checker forbids this.
这只是行不通 - 借用检查员禁止这样做。
Can you work around this? 你能解决这个问题吗? Yes!
是! The usual trick when working with vectors or arrays is to delay all borrows by iterating over the indices instead.
使用向量或数组时,通常的技巧是通过迭代索引来延迟所有借用。 So write something like this:
所以写这样的东西:
for i in 0..cell_states.len() {
for j in 0..cell_states[i].len() {
...
}
}
The vector is not borrowed in that case, but you can borrow elements of it later by just indexing it. 在这种情况下,向量不会被借用,但您可以稍后通过索引来借用它的元素。
But: the borrow checker just saved you, because what you attempted was buggy! 但是:借用检查员只是拯救了你,因为你的尝试是错误的! What you tried is not how Game of Life works!
你尝试的不是生命游戏的运作方式! You need two grids of cells, because the update step cannot update all cells on the fly.
您需要两个网格单元格,因为更新步骤无法动态更新所有单元格。 You first have to calculate all new cells into a new vector (so that you can use all the old cell values while calculating the new ones) and then you can replace the old vector with the new one.
首先必须将所有新单元格计算为新向量(以便在计算新单元格时可以使用所有旧单元格值),然后可以用新单元格替换旧单元格。 So the update step in Game of Life is a two step process -- you cannot do it in-place.
因此,Game of Life中的更新步骤是一个两步过程 - 您无法就地执行此操作。
And after fixing that real bug, you will find that you won't run into this specific borrow checker problem again. 在修复了这个真正的bug之后,你会发现你不会再遇到这个特定的借用检查器问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.