问题
简而言之:我正在尝试实现一个struct
,它包含一个闭包的回调,它可变地捕获状态。想法是用户提供回调(闭包),当特定事件发生时,用户可以得到通知。
我有一个工作的概念验证版本(代码示例#1)。
此插件工作原理(code sample #1):
fn fun<F>(f: F) -> F
where
F: FnMut() -> (),
{
f
}
fn main() {
let mut abc = "abc".to_string();
let mut f = fun(|| {
abc.push_str(".");
println!("closure: {:?}", abc);
});
f();
f();
f();
println!("end: {:?}", abc);
}
字符串
输出量:
closure: "abc."
closure: "abc.."
closure: "abc..."
end: "abc..."
型
失败(code sample #2):
与前面的想法相同(略有不同),但试图在Foo
中包含闭包。
struct Foo<'a, T> {
pub cb: Box<dyn FnMut(&T) + 'a>,
}
impl<'a, T> Foo<'a, T> {
fn new(f: impl FnMut(&T) + 'a) -> Self {
Self { cb: Box::new(f) }
}
fn on_change(&mut self, f: impl FnMut(&T) + 'a)
{
self.cb = Box::new(f);
}
}
impl<'a, T> Default for Foo<'a, T>
{
fn default() -> Self {
Self::new(|_| {})
}
}
fn main() {
let mut abc = "abc".to_string();
let mut f = Foo::default();
f.on_change(|a| {
abc.push_str("."); // PROBLEM HERE; uncomment and it works!
println!("- param: {:?}", a);
});
let param = "a".to_string();
(f.cb)(¶m);
(f.cb)(¶m);
(f.cb)(¶m);
println!("end: {:?}", abc);
}
型
预期产出:
- param: "a"
- param: "a"
- param: "a"
end: "abc..."
型
实际输出(编译器错误):
error[E0502]: cannot borrow `abc` as immutable because it is also borrowed as mutable
--> src/main.rs:33:27
|
25 | f.on_change(|a| {
| --- mutable borrow occurs here
26 | abc.push_str("."); // PROBLEM HERE; uncomment and it works!
| --- first borrow occurs due to use of `abc` in closure
...
33 | println!("end: {:?}", abc);
| ^^^ immutable borrow occurs here
34 | }
| - mutable borrow might be used here, when `f` is dropped and runs the destructor for type `Foo<'_, String>`
型
编译器的错误很明显,它肯定与生命周期有关。我想我的问题是我需要告诉编译器闭包和它的参数生命周期-但问题是,如何告诉编译器?
如何修改代码示例#2,让回调注册工作像代码示例#1一样?
REPL:
1条答案
按热度按时间xiozqbni1#
abc
仍然绑定在f
中。f
存在于main
中,所以f
在main结束时被销毁,这意味着在println
期间,f
仍然存在并绑定abc
。为了更早地销毁一个变量,你必须有以下可能性:
drop
关于
drop
:字符串
这里有一个嵌套的作用域:
型
这两个代码段都将打印:
型