如何存储使用封闭状态的 Rust 闭包

How to store Rust closures that use enclosing state

我找到了两种方法 return 从使用封闭状态的函数中闭包:

fn closure_try(t: u64) -> Box<dyn Fn(u64) -> u64> {
    let f = |x: u64| x + t;
    return Box::new(f);
}

fn closure_try2(t: u64) -> impl Fn(u64) -> u64 {
    let f = move |x: u64| x + t.clone();
    return f;
}

现在,我需要将输出对象存储到一个结构中,并且还能够克隆它。

不幸的是,在第二种情况下,特征 impl 对象不能位于结构位置。

struct A {
    b: impl Fn(u64) -> u64
}

这失败了:impl Trait 不允许超出函数和方法 return 类型。

在第一个示例中,无法复制或克隆装箱的动态特征对象。

fn duplicate(f: Box<dyn Fn(u64) -> u64>) -> Box<dyn Fn(u64) -> u64> {
    f.clone()
}

这失败并出现错误“不满足 dyn Fn(u64) -> u64: Clone

创建闭包存储的惯用方法是什么:

我正在考虑的一个选择是让这些函数 return 一个闭包 return 闭包,但这似乎有问题。

您可以使用自定义方法来克隆 Box<dyn Trait>,请参阅

trait ClonableFn: Fn(u64) -> u64 {
    fn clone_box(&self) -> Box<dyn ClonableFn>;
}
impl Clone for Box<dyn ClonableFn> {
    fn clone(&self) -> Self {
        <dyn ClonableFn>::clone_box(&**self)
    }
}
impl<T> ClonableFn for T
where
    T: 'static + Fn(u64) -> u64 + Clone,
{
    fn clone_box(&self) -> Box<dyn ClonableFn> {
        Box::new(T::clone(self))
    }
}

fn closure_try(t: u64) -> Box<dyn ClonableFn> {
    let f = move |x: u64| x + t;
    Box::new(f)
}

Playground.

或者,您可以使用不稳定特性type_alias_impl_trait来命名第二种方法的return类型:

#![feature(type_alias_impl_trait)]

type ClosureType = impl Fn(u64) -> u64 + Clone;
fn closure_try(t: u64) -> ClosureType {
    move |x: u64| x + t
}

Playground

后一种方法性能更高,但 nightly-only 截至今天。