是否可以将闭包分配给impl Fn()类型的变量?

时间:2019-01-19 18:08:38

标签: types rust closures

我能够使这段代码起作用:

docker system prune --volumes

但是,我想要的是这个(没有拳击):

docker-compose up -d

有没有一种方法可以使第二部分代码工作而无需装箱,使用特征,类型转换或任何其他方法? Rust抱怨类型不匹配。

2 个答案:

答案 0 :(得分:4)

如果没有拳击,则无法完成此操作。原因是输入中的fst的实际类型与您以后用其关闭的闭包的类型不同。使它们具有相同类型的唯一方法是使用trait对象。

盒装版本可能看起来像这样:

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);
}

但是我真的不确定为什么要这么做!

答案 1 :(得分:1)

回答您的问题 ,不,您尚未为类型impl Fn的变量分配闭包,因为您尚未声明这样的变量:

fn foo() {
    let x: impl Fn() = move || println!("Hello");
}
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
 --> src/lib.rs:2:12
  |
2 |     let x: impl Fn() = move || println!("Hello");
  |            ^^^^^^^^^

“但是等等!”您说,“我的函数参数中有这种类型!”。事实是,不,你不会。

此语法:

fn foo(x: impl Fn()) {}

这只是它的简写:

fn foo<F>(x: F)
where
    F: Fn(),
{}

您仅构造了一个泛型并对其绑定了一个特征。

另请参阅: