修改
我正在尝试在函数内创建闭包向量,向向量添加标准闭包,然后从函数返回向量。我收到了关于生命冲突的错误。
代码可以执行here。
fn vec_with_closure<'a, T>(f: Box<FnMut(T) + 'a>) -> Vec<Box<FnMut(T) + 'a>>
{
let mut v = Vec::<Box<FnMut(T)>>::new();
v.push(Box::new(|&mut: t: T| {
f(t);
}));
v
}
fn main() {
let v = vec_with_closure(Box::new(|t: usize| {
println!("{}", t);
}));
for c in v.iter_mut() {
c(10);
}
}
编辑2:
使用Rc<RefCell<...>>
和move ||
以及Fn()
特征而不是Shepmaster建议的FnMut()
m,帮助我生成了上述代码的工作版本。 Rust围栏版本here。
答案 0 :(得分:1)
这是我对这个问题的理解,略微缩小了:
fn filter<F>(&mut self, f: F) -> Keeper
where F: Fn() -> bool + 'static //'
{
let mut k = Keeper::new();
self.subscribe(|| {
if f() { k.publish() }
});
k
}
在此方法中,f
是一个已按值传递的值,这意味着filter
拥有它。然后,我们创建另一个闭包,用于捕获f
by-reference 。然后我们尝试在某处保存该闭包,因此闭包中的所有引用都需要比我们结构的生命周期更长(为方便起见,我选择'static
。)
但是,f
只会持续到方法结束,所以它肯定不会活得足够长。我们需要使闭包拥有f
。如果我们可以使用move
关键字,但这会导致闭包也在k
中移动,那将是理想的,因此我们无法从函数中返回它。
试图解决这个问题导致了这个版本:
fn filter<F>(&mut self, f: F) -> Keeper
where F: Fn() -> bool + 'static //'
{
let mut k = Keeper::new();
let k2 = &mut k;
self.subscribe(move || {
if f() { k2.publish() }
});
k
}
有一条有用的错误消息:
error: `k` does not live long enough
let k2 = &mut k;
^
note: reference must be valid for the static lifetime...
...but borrowed value is only valid for the block
这会导致另一个问题:您尝试在闭包中保留对k
的引用,但只要从函数返回k
,该引用就会变为无效。当项目按值移动时,它们的地址将会改变,因此引用不再有效。
fn filter<F>(&mut self, f: F) -> Rc<RefCell<Keeper>>
where F: Fn() -> bool + 'static //'
{
let mut k = Rc::new(RefCell::new(Keeper::new()));
let k2 = k.clone();
self.subscribe(move || {
if f() { k2.borrow_mut().publish() }
});
k
}