我能够使这段代码工作:
fn twice<T: Clone>(fst: impl Fn(T), snd: impl Fn(T)) -> impl Fn(T) {
move |t| {
fst(t.clone());
snd(t)
}
}
然而,我想要的是这个(没有装箱):
fn sub<T: Clone>(mut fst: impl Fn(T), snd: impl Fn(T)) {
fst = move |t: T| {
fst(t.clone());
snd(t)
};
}
有没有一种方法可以使第二段代码无需装箱、使用特征、类型转换或任何其他方法就可以工作? Rust 提示类型不匹配。
最佳答案
如果没有装箱,这是做不到的。原因是输入中 fst
的实际类型与您稍后覆盖它的闭包类型不同。使它们成为同一类型的唯一方法是使用特征对象。
盒装版本可能如下所示:
use std::mem;
fn sub<'a, T: Clone + 'a>(fst: &mut Box<dyn Fn(T) + 'a>, snd: impl Fn(T) + 'a) {
// Replace the original fst with a dummy closure while the new closure is being
// constructed, to avoid the reference being temporarily invalid
let fst_orig = mem::replace(fst, Box::new(|_| {}));
*fst = Box::new(move |t: T| {
fst_orig(t.clone());
snd(t)
});
}
fn main() {
let mut f1: Box<dyn Fn(i32)> = Box::new(|x| println!("f1: {}", x));
let f2 = |x| println!("f2: {}", x);
sub(&mut f1, f2);
f1(42);
}
但我真的不确定你为什么要这样做!
关于types - 是否可以将闭包分配给 impl Fn() 类型的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54269942/