【发布时间】:2021-05-31 04:38:40
【问题描述】:
我目前正在自学 Rust,并且正在通过实现井字游戏来练习。
我有一个 Board 结构(Cell 和 GameState 是简单的枚举,SIZE 是 3 usize):
struct Board {
state : GameState,
cells : [[Cell; SIZE]; SIZE],
}
我正在尝试实现mark 方法:
impl Board {
fn mark(&mut self, pos: &Position, player: Player) {
// various checks omitted
// mark cell for player
self.cells[pos.row][pos.col] = Cell::Filled(player);
// check whether player has won either via a full row or column (diagonals omitted):
if (0..SIZE).map(|i| &self.cells[pos.row][i]).all(|c| *c == Cell::Filled(player)) ||
(0..SIZE).map(|i| &self.cells[i][pos.col]).all(|c| *c == Cell::Filled(player)) {
self.state = GameState::Winner(player);
}
}
到目前为止一切都很好......但是有丑陋的代码重复。
所以我的下一步是引入一个闭包并用它替换 if 中的重复:
let all_in_line = |cell_access| (0..SIZE).map(cell_access).all(|c : &Cell| *c == Cell::Filled(player));
if all_in_line(|i : usize| &self.cells[pos.row][i]) ||
all_in_line(|i : usize| &self.cells[i][pos.col]) {
但这不起作用,因为它需要all_in_line 是通用的(因为我传递给它的两个闭包具有不同的匿名类型),所以我的下一步是做一些类似于类型擦除的事情:
fn mark(&mut self, pos: &Position, player: Player) {
let all_in_line = |cell_access : Box<dyn Fn(usize) -> &Cell>| (0..SIZE).map(cell_access).all(|c : &Cell| *c == Cell::Filled(player));
if all_in_line(Box::new(|i : usize| &self.cells[pos.row][i])) ||
all_in_line(Box::new(|i : usize| &self.cells[i][pos.col])) {
self.state = GameState::Winner(player);
}
但是现在 rust 编译器抱怨 cell_access 的类型说明符中返回的引用缺少生命周期参数:
error[E0106]: missing lifetime specifier
let all_in_line = |cell_access : Box<dyn Fn(usize) -> &Cell>| (0..SIZE).map(cell_access).all(|c : &Cell| *c == Cell::Filled(player));
^ expected named lifetime parameter
我尝试将mark 修改为fn mark<'a>(&'a mut self, /*...*/) 并相应地更新cell_access 的类型:Box<dyn Fn(usize) -> &'a Cell>,但这失败了:
error[E0597]: `self` does not live long enough
fn mark<'a>(&'a mut self, pos: &Position, player: Player) {
-- lifetime `'a` defined here
...
if all_in_line(Box::new(|i : usize| &self.cells[pos.row][i]))
----------- -^^^^------------------
| ||
| |borrowed value does not live long enough
| returning this value requires that `self` is borrowed for `'a`
value captured here
...
}
- `self` dropped here while still borrowed
此时,我已经想不出问题出在哪里以及如何解决它。
【问题讨论】: