如何在成员函数调用的闭包中修改 self?
How can I modify self in a closure called from a member function?
我正在尝试计算合法的国际象棋走法,但无法满足借用检查员的要求。我有一个实现这些方法的结构Chess
(不重要的代码替换为...
):
// internal iterator over (possibly not legal) moves
fn get_moves<F>(&self, func: F)
where
F: Fn(/* ... */),
{
func(/* ... */); // move 1
func(/* ... */); // move 2
func(/* ... */); // etc...
}
fn is_legal_move(&mut self) -> bool {
// notice this takes a mutable self. For performance
// reasons, the move is made, legality is checked, then I
// undo the move, so it must be mutable to be able to move pieces
make_move(/* ... */);
// check if legal
undo_move(/* ... */);
//return true if legal
}
fn get_legal_moves(&self) /* -> ... */ {
self.get_moves(|/* ... */| {
if self.is_legal_move(/* ... */) { // <-- error here
// do something with legal move
}
})
}
我在 get_legal_moves
中遇到编译错误,因为我在闭包内修改 self
而 get_moves
仍在借用 self
。
我创建了一个简化示例来展示我要解决的问题:
struct Tester {
x: i8,
}
impl Tester {
fn traverse<Func>(&mut self, mut f: Func)
where
Func: FnMut(),
{
//in real-world, this would probably iterate over something
f();
}
}
fn main() {
let mut tester = Tester { x: 8 };
tester.traverse(|| {
tester.x += 1; //I want to be able to modify tester here
});
println!("{}", tester.x);
}
错误:
error[E0499]: cannot borrow `tester` as mutable more than once at a time
--> src/main.rs:17:5
|
17 | tester.traverse(|| {
| ^ -------- -- first mutable borrow occurs here
| | |
| _____| first borrow later used by call
| |
18 | | tester.x += 1; //I want to be able to modify tester here
| | ------ first borrow occurs due to use of `tester` in closure
19 | | });
| |______^ second mutable borrow occurs here
error[E0499]: cannot borrow `tester` as mutable more than once at a time
--> src/main.rs:17:21
|
17 | tester.traverse(|| {
| ------ -------- ^^ second mutable borrow occurs here
| | |
| | first borrow later used by call
| first mutable borrow occurs here
18 | tester.x += 1; //I want to be able to modify tester here
| ------ second borrow occurs due to use of `tester` in closure
我怎样才能满足借用检查器的要求,以便代码可以编译?
您可以进行的最简单更改是将引用传递给闭包:
struct Tester {
x: i8,
}
impl Tester {
fn traverse<F>(&mut self, mut f: F)
where
F: FnMut(&mut Tester),
{
f(self);
}
}
fn main() {
let mut tester = Tester { x: 8 };
tester.traverse(|z| z.x += 1);
println!("{}", tester.x);
}
这可以防止有多个可变引用(也称为 别名),这在 Rust 中是不允许的。
我正在尝试计算合法的国际象棋走法,但无法满足借用检查员的要求。我有一个实现这些方法的结构Chess
(不重要的代码替换为...
):
// internal iterator over (possibly not legal) moves
fn get_moves<F>(&self, func: F)
where
F: Fn(/* ... */),
{
func(/* ... */); // move 1
func(/* ... */); // move 2
func(/* ... */); // etc...
}
fn is_legal_move(&mut self) -> bool {
// notice this takes a mutable self. For performance
// reasons, the move is made, legality is checked, then I
// undo the move, so it must be mutable to be able to move pieces
make_move(/* ... */);
// check if legal
undo_move(/* ... */);
//return true if legal
}
fn get_legal_moves(&self) /* -> ... */ {
self.get_moves(|/* ... */| {
if self.is_legal_move(/* ... */) { // <-- error here
// do something with legal move
}
})
}
我在 get_legal_moves
中遇到编译错误,因为我在闭包内修改 self
而 get_moves
仍在借用 self
。
我创建了一个简化示例来展示我要解决的问题:
struct Tester {
x: i8,
}
impl Tester {
fn traverse<Func>(&mut self, mut f: Func)
where
Func: FnMut(),
{
//in real-world, this would probably iterate over something
f();
}
}
fn main() {
let mut tester = Tester { x: 8 };
tester.traverse(|| {
tester.x += 1; //I want to be able to modify tester here
});
println!("{}", tester.x);
}
错误:
error[E0499]: cannot borrow `tester` as mutable more than once at a time
--> src/main.rs:17:5
|
17 | tester.traverse(|| {
| ^ -------- -- first mutable borrow occurs here
| | |
| _____| first borrow later used by call
| |
18 | | tester.x += 1; //I want to be able to modify tester here
| | ------ first borrow occurs due to use of `tester` in closure
19 | | });
| |______^ second mutable borrow occurs here
error[E0499]: cannot borrow `tester` as mutable more than once at a time
--> src/main.rs:17:21
|
17 | tester.traverse(|| {
| ------ -------- ^^ second mutable borrow occurs here
| | |
| | first borrow later used by call
| first mutable borrow occurs here
18 | tester.x += 1; //I want to be able to modify tester here
| ------ second borrow occurs due to use of `tester` in closure
我怎样才能满足借用检查器的要求,以便代码可以编译?
您可以进行的最简单更改是将引用传递给闭包:
struct Tester {
x: i8,
}
impl Tester {
fn traverse<F>(&mut self, mut f: F)
where
F: FnMut(&mut Tester),
{
f(self);
}
}
fn main() {
let mut tester = Tester { x: 8 };
tester.traverse(|z| z.x += 1);
println!("{}", tester.x);
}
这可以防止有多个可变引用(也称为 别名),这在 Rust 中是不允许的。