借用检查器停止迭代器在递归功能中调用for_each
我正在Rust和Wasm上的一份扫雷副本。目前,我正在完成清洗矿井的逻辑。主要是,当用户单击一个空的瓷砖,附近没有炸弹时,该程序随后搜索邻居并揭示这些瓷砖,如果它们不在任何炸弹附近。
请注意,游戏中自动打开的大空格。
该程序使用两个1D向量存储炸弹所在的位置,而每个图块的状态是什么。
然后,此递归程序将发现的空瓷砖的状态设置为SpotState ::空,然后与邻居继续使用。
/// for uncovering empty neighbors and recursively uncovering their empty neighbors
fn uncover_empty_neighbors(&mut self, col: usize, row: usize) {
// break case for recursion
if self.state_vec[self.get_idx(col, row)] == SpotState::Empty {
return;
}
if self.get_mine_neighbor_count(col, row) == 0 {
let idx = self.get_idx(col, row);
self.state_vec[idx] = SpotState::Empty;
}
let inbound_neighbors = POSSIBLE_NEIGHBORS
.iter()
.map(|[x, y]| [x + col as isize, y + row as isize])
.filter(|[x, y]| self.check_bounds(x, y))
.for_each(|[x, y]| self.uncover_empty_neighbors(x as usize, y as usize));
}
但是,我遇到了这个错误:
error[E0500]: closure requires unique access to `*self` but it is already borrowed
--> src\lib.rs:138:23
|
137 | .filter(|[x, y]| self.check_bounds(x, y))
| -------- ---- first borrow occurs due to use of `*self` in closure
| |
| borrow occurs here
138 | .for_each(|[x, y]| {
| -------- ^^^^^^^^ closure construction occurs here
| |
| first borrow later used by call
139 | self.uncover_empty_neighbors(x as usize, y as usize)
| ---- second borrow occurs due to use of `*self` in closure
For more information about this error, try `rustc --explain E0500`.
error: could not compile `minesweeper_wasm` due to previous error
warning: build failed, waiting for other jobs to finish...
error: build failed
我对如何实现这一目标感到困惑。闭合是否无法捕获self
,因为self
已经在函数undover_empty_neighbors()
中借用了?在这种情况下,使用self
不可避免地会出现不良的动作,哪些其他数据结构将有用?
I am working on a minesweeper copy in Rust and WASM. At the moment, I'm finishing the logic for Mine Sweeper. Mainly, when the user clicks on an empty tile with no bombs near it, the program then searches the neighbors and reveals those tiles if they are not near any bombs.
Notice the large empty spaces on the game that opens up automatically.
The program uses two 1D vectors to store where the bombs are and also what is the state of each tile.
Then this recursive program sets the state of a found empty tile to SpotState::Empty, then continues this with the neighbors.
/// for uncovering empty neighbors and recursively uncovering their empty neighbors
fn uncover_empty_neighbors(&mut self, col: usize, row: usize) {
// break case for recursion
if self.state_vec[self.get_idx(col, row)] == SpotState::Empty {
return;
}
if self.get_mine_neighbor_count(col, row) == 0 {
let idx = self.get_idx(col, row);
self.state_vec[idx] = SpotState::Empty;
}
let inbound_neighbors = POSSIBLE_NEIGHBORS
.iter()
.map(|[x, y]| [x + col as isize, y + row as isize])
.filter(|[x, y]| self.check_bounds(x, y))
.for_each(|[x, y]| self.uncover_empty_neighbors(x as usize, y as usize));
}
However, I get this error:
error[E0500]: closure requires unique access to `*self` but it is already borrowed
--> src\lib.rs:138:23
|
137 | .filter(|[x, y]| self.check_bounds(x, y))
| -------- ---- first borrow occurs due to use of `*self` in closure
| |
| borrow occurs here
138 | .for_each(|[x, y]| {
| -------- ^^^^^^^^ closure construction occurs here
| |
| first borrow later used by call
139 | self.uncover_empty_neighbors(x as usize, y as usize)
| ---- second borrow occurs due to use of `*self` in closure
For more information about this error, try `rustc --explain E0500`.
error: could not compile `minesweeper_wasm` due to previous error
warning: build failed, waiting for other jobs to finish...
error: build failed
I'm confused about how to accomplish this. Is the closure unable to capture self
since self
is already mutably borrowed in the function uncover_empty_neighbors()
? Is using self
inevitably a bad move in this case and what other data structure would be useful?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的。请记住,对迭代器进行了懒惰的评估,因此将闭合传递到
过滤器
需要借用self
and 继续借用它,而for_each
正在执行,因为for_each
需要评估调用它的迭代器。您可以尝试重组代码,以便任何方法都不取决于
self
,也可以简单地collect()
纳入新的vec
filter()
之后,因此没有不变的借入活着的借款为undover_empty_neighbors
执行。Yes. Remember that iterators are evaluated lazily, so the closure passed into
filter
needs to borrowself
and keep borrowing it whilefor_each
is executing, asfor_each
needs to evaluate the iterator it is called on.You can either try to restructure the code so that either of the methods does not depend on
self
, or you can simplycollect()
into a newVec
after thefilter()
, so that there is no immutable borrow alive asuncover_empty_neighbors
executes.您只需要尽可能避免借钱即可。在这种情况下,考虑
宽度/高度
的免费方法,考虑到它们是usize
,是copy> copy> copy
“好吧,您正在用迭代器使用的封闭捕获
self
,因为迭代器懒惰,直到收集 borrow 才能释放(或者在您的情况下(在您的情况下,整个)评估for_each
)。You just need to try to avoid borrowing when possible. In this case making a free method taking an owned
width/height
is enough, considering that they areusize
which isCopy
:Playground
What is going on? Well, you are capturing
self
withing the closures that the iterator use, since iterators are lazy thatborrow
is not release until you collect (or in your case the wholefor_each
is evaluated).