将类型的实例从参数列表传递到函数声明(动态环境捕获)



我在这里制作了一个实现优化算法的库。这些是相关功能和特征的签名:

pub fn cmaes_loop<T>(object: &T, options: CMAESOptions) -> Option<Vec<f64>>
    where T: 'static + FitnessFunction
pub trait FitnessFunction {
    fn get_fitness(&self, parameters: &[f64]) -> f64;
}

如果我将函数库应用于一个简单的问题,我可以根据给定的参数计算适应度。但是,假设我想针对给定的尺寸和材料优化机翼的形状:

struct Wing<'a> {
    material: String,
    size: i32,
    parameters: &'a [f64]
}

我可以实现适应度函数来读取其他字段并将它们分解到计算中,然后给cmaes_loop函数一个Wing实例,以优化特定的材料和尺寸。我正在制作另一个将使用这个的库。它优化了其他内容(如Wing(,所以我有一个包装器特征可以使第二个库更易于使用:

pub trait WingFitnessFunction {
    fn get_fitness(&self, wing: &Wing) -> f64;
}

我像这样实现FitnessFunction特征:

impl FitnessFunction for Wing {
    fn get_fitness(&self, parameters: &[f64]) -> f64 {
        let wing = Wing {
            parameters: parameters,
            .. self
        };
        // error here
        let result = WingFitnessFunction::get_fitness(wing);
    }
}

WingFitnessFunction有一个&self论点,原因与FitnessFunction相同。我希望我的第二个库的用户能够传递实现WingFitnessFunction的其类型的实例。我将FitnessFunctionimpl放入一个函数的主体中,该函数采用用户类型的实例:

fn foo<T: WingFitnessFunction>(object: T) {
    impl FitnessFunction for Wing {
        ...
        object.get_fitness(wing)
    }

但是当我尝试调用get_fitness方法object时,出现此错误:

无法捕获 FN 项目中的动态环境;请使用 ||{ ... }改为关闭形式

我需要知道如何在特定实例上调用objectget_fitness方法(闭包可以做到这一点,但我不知道如何使其与 cmaes_loop 函数一起使用(。

我的问题的解决方案是添加一个包装器:

struct WingWrapper<'a, T: WingFitnessFunction> {
    wing: Wing,
    object: T
}

并为其实现FitnessFunction

impl<'a, T: WingFitnessFunction> FitnessFunction for WingWrapper<'a, T> {
    fn get_fitness(&self, parameters: &[f64]) -> f64 {
        let wing = Wing {
            parameters: parameters,
            .. self.wing
        }
        self.object.get_fitness(&wing)
    }
}

在将实现WingFitnessFunction的类型作为参数的函数中,首先构建一个WingWrapper

let wrapper = WingWrapper {
    wing: // Instance of wing here
    object: // Instance of object here (taken as an argument)
}

现在,您可以通过FitnessFunction的方法从WingFitnessFunction特征调用get_fitness方法:

println!("{}", wrapper.get_fitness(&[1, 2, 3]));

这不会增加使用库的任何困难;从用户的角度来看,它是完全相同的。

相关内容

  • 没有找到相关文章

最新更新