Arn*_*e J 9 mutability rust borrow-checker
我正在通过锻炼来学习Rust。在此文件中,目标是像在电子表格中一样更新单元格:当值更改时,必须重新计算从该单元格派生的所有单元格。在这里,这些被称为该单元的父母。
更新单元格的值证明没有问题,但是更新父母会使我与借贷检查器发生冲突。从a检索单元格HashMap并更新值后,我不再需要可变的引用-因此我尝试将其包装在不可变的引用中。这样,我只需要找到一次即可。
但是似乎Rust的数字是因为我最初从借来的书中得到了我一成不变的参考&mut self,所以它仍然必须与之绑定。显然,这使我无法再次使用self。
use std::collections::HashMap;
use std::vec::Vec;
struct Cell {
value: i32,
parents: Vec<u32>,
}
pub struct Sheet {
table: HashMap<u32, Cell>,
}
impl Sheet {
pub fn set_value(&mut self, identifier: u32, new_value: i32) {
let mut updated_cell: Option<&Cell> = None;
if let Some(cell) = self.table.get_mut(&identifier) {
let Cell { value, .. } = cell;
*value = new_value;
updated_cell = Some(cell);
}
if let Some(cell) = updated_cell {
recalculate(self, &cell.parents);
}
}
}
fn recalculate(_sheet: &mut Sheet, _cells: &[u32]) {}
Run Code Online (Sandbox Code Playgroud)
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/lib.rs:20:16
|
16 | if let Some(cell) = self.table.get_mut(&identifier) {
| ---------- first mutable borrow occurs here
...
22 | recalculate(self, &cell.parents);
| ^^^^ ------------- first borrow later used here
| |
| second mutable borrow occurs here
Run Code Online (Sandbox Code Playgroud)
我想知道是否有避免第二次搜索或避免不必要的矢量副本的解决方案。我已经尝试过多次调整代码,但是并不是所有语法都对我来说还不清楚。
Rust 可以保护您免受潜在危险的影响。的签名中没有任何内容recalculate可以保证它不会发生突变sheet,从而导致 中的引用cells变得无效。例如,recalculate 可以删除一些单元格,然后其中的引用cell.parents将是悬空指针。
您可能需要传递父细胞的克隆:
if let Some(cell) = updated_cell {
let parents = cell.parents.clone();
recalculate(self, &parents);
}
Run Code Online (Sandbox Code Playgroud)
或者,您可能需要考虑不同的数据模型,它将单个单元的可变性与整体结构的可变性分开。例如,您可以将单元格包装在 astd::cell::Cell或中std::cell::RefCell,并将不可变引用传递给Sheet.