Rust 无法移出'FnMut'闭包中捕获的变量
我对错误的理解是:Rust 无法移出'FnMut'闭包中捕获的变量,rust,Rust,我对错误的理解是: 闭包B是FnMut,它通过获取其所有权来捕获通知者 在闭包B中,send再次需要获得所有权 现在send和Closure B都在修改notificator,从而修改错误 我的理解正确吗?如何解决这个问题?嵌套闭包很棘手 考虑这一点: pub fn create_future( notificator: mpsc::Sender<usize>, proxy: Proxy, ) -> impl Future<Item = (), Error
FnMut
,它通过获取其所有权来捕获通知者
send
再次需要获得所有权send
和Closure B都在修改notificator
,从而修改错误我的理解正确吗?如何解决这个问题?嵌套闭包很棘手 考虑这一点:
pub fn create_future(
notificator: mpsc::Sender<usize>,
proxy: Proxy,
) -> impl Future<Item = (), Error = ()> {
proxy.something()
.and_then(move |sub| {
sub.for_each(move |a| { // <---- Closure A
proxy.something_else(a)
.and_then(move |b| { // <---- Closure B
notificator.send(b.len()); // <---- Error!
Ok(())
})
.or_else(|e| {
panic!("oops {}", e);
Ok(())
})
})
})
.map_err(|e| {
()
})
}
然后,您会看到所看到的错误(除了Fn
vsFnMut
,这对问题无关紧要)。每次调用外部闭包时,都会重新创建内部闭包(必须这样做,因为它每次都要捕获a
),但它每次都会尝试通过移动来捕获外部闭包。这行不通;第一次之后,outer\u s
被移出,因此无效
要将此映射回您的代码,说“Closure B capturesnotificator
”是错误的,因为不只是一个Closure B。有尽可能多的必要的Closure B,但是通常您嵌套的和_然后
和for_每个
调用都会在该代码段中结束。但只有一个人可以通过移动来捕获
所以要解决这个问题,您需要确保只有一个闭包B,或者确保每个人都有足够的mpsc::Sender
s
第一种方法是将闭包从嵌套上下文中拉出
fn use_a_fn_multiple_times(f: impl Fn(String)) {
f("foo".to_owned());
f("bar".to_owned());
}
fn use_fn_once(f: impl FnOnce() -> Vec<u8>) {
println!("Bytes: {:?}", f());
}
fn main() {
let outer_s = "see:".to_owned();
use_a_fn_multiple_times(|a: String| {
use_fn_once(move || {
let mut v = outer_s.into_bytes();
v.extend(a.into_bytes());
v
});
});
}
第二种方法涉及大量的clone()
调用,由于我无法对代码进行类型检查,因此我不会尝试编写它
但是,当所有这些都说了又做了之后,您的代码仍然会失败,因为您正在移出代理
,同时也在尝试使用它。什么是代理
?你能提供一个“请”吗?“在结束语B中,再次发送需要获得所有权”-听起来不对mpsc::Sender::send
接受&self
。我相信您的问题已经由的答案回答了。如果你不同意,请用你的问题来解释不同之处。否则,我们可以将此问题标记为已回答。谢谢。非常有用。我最终通过添加clone()
s来修复它。或者在我的例子中,当我想使用一个struct
时,需要在嵌套的FnMut
中使用顶级参数来调用它,然后我首先用#[derivate(clone)]
注释该结构,以便能够使用clone()
。
fn use_a_fn_multiple_times(f: impl Fn(String)) {
f("foo".to_owned());
f("bar".to_owned());
}
fn use_fn_once(f: impl FnOnce() -> Vec<u8>) {
println!("Bytes: {:?}", f());
}
fn main() {
let outer_s = "see:".to_owned();
use_a_fn_multiple_times(|a: String| {
use_fn_once(move || {
let mut v = outer_s.into_bytes();
v.extend(a.into_bytes());
v
});
});
}
let closure_b = move |b| {
notificator.send(b.len());
Ok(())
};
proxy.something()
.and_then(move |sub| {
sub.for_each(move |a| { // <---- Closure A
proxy.something_else(a)
.and_then(closure_b)
.or_else(|e| {
panic!("oops {}", e);
Ok(())
})
})
})
.map_err(|e| {
()
})
let closure_b = move |b| {
notificator.send(b.len());
Ok(())
};
let closure_a = move |a| {
proxy.something_else(a)
.and_then(closure_b)
.or_else(|e| {
panic!("oops {}", e);
Ok(())
})
};
proxy.something()
.and_then(move |sub| {
sub.for_each(closure_a)
})
.map_err(|e| {
()
})