如何将具有捕获的可变变量的回调视为正常的可变借用? [英] How can callbacks with captured mutable variables be treated like normal mutable borrows?
问题描述
Foo
可以使用方法 .modify()
进行修改:
Foo
can be modified using the method .modify()
:
struct Foo;
impl Foo {
fn modify(&mut self) {}
}
Bar
存储回调:
struct Bar<'a> {
callback: Box<FnMut() + 'a>,
}
impl<'a> Bar<'a> {
fn new<F: FnMut() + 'a>(f: F) -> Bar<'a> {
Bar {
callback: Box::new(f),
}
}
}
init()
取一片 Bar
并执行它们的回调:
init()
takes a slice of Bar
and executes their callbacks:
fn init(bars: &mut [Bar]) {
for b in bars {
(*b.callback)();
}
}
现在是最有趣的:
在循环中更改 Foo
工作正常;在循环的每次迭代中 foo
被可变地借用并且 .modify()
被调用:
Changing Foo
in a loop works fine; on each iteration of the loop foo
is mutably borrowed and .modify()
is called:
fn main() {
let mut foo = Foo;
for _ in 0..10 {
foo.modify();
}
}
在回调内部更改 Foo
不起作用:
Changing Foo
inside of the callbacks does not work:
fn main() {
let mut foo = Foo;
let mut bar1 = Bar::new(|| foo.modify());
let mut bar2 = Bar::new(|| foo.modify());
init(&mut [bar1, bar2]);
}
在操场上试试,它有一个错误:
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> src/main.rs:27:29
|
26 | let mut bar1 = Bar::new(|| foo.modify());
| -- --- previous borrow occurs due to use of `foo` in closure
| |
| first mutable borrow occurs here
27 | let mut bar2 = Bar::new(|| foo.modify());
| ^^ --- borrow occurs due to use of `foo` in closure
| |
| second mutable borrow occurs here
...
30 | }
| - first borrow ends here
如何为第 2 项实施类似的保证?
How to implement a similar guarantee for item 2?
推荐答案
您可以使用 RefCell
:
You can use RefCell
:
let foo = RefCell::new(Foo);
{
let bar1 = Bar::new(|| foo.borrow_mut().modify());
let bar2 = Bar::new(|| foo.borrow_mut().modify());
init(&mut [bar1, bar2]);
}
let mut foo = foo.into_inner(); // extract foo to use in external API
小心borrow_mut()
,如果值当前被借用,它会发生恐慌.
Be careful with borrow_mut()
, it panics if the value is currently borrowed.
如果你可以改变Bar
和init()
,你可以将值foo
传递给init()
> 与方法 modify()
分开:
If you can change Bar
and init()
, you can pass value foo
to the init()
separate from the method modify()
:
struct Bar<'a> {
callback: Box<FnMut(&mut Foo) + 'a>,
}
impl<'a> Bar<'a> {
fn new<F: FnMut(&mut Foo) + 'a>(f: F) -> Bar<'a> {
Bar {
callback: Box::new(f),
}
}
}
fn init(bars: &mut [Bar], arg: &mut Foo) {
for b in bars {
(*b.callback)(arg);
}
}
let mut bar1 = Bar::new(|x| x.modify());
let mut bar2 = Bar::new(Foo::modify); // you can pass it without closure
init(&mut [bar1, bar2], &mut foo);
这篇关于如何将具有捕获的可变变量的回调视为正常的可变借用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!