在函数中捕获变量的结构



是否可以构建结构

struct MyFn<A, B> {
call: fn(A) -> B
}

这样它就能够像下面的代码片段中那样捕获不可变的变量?

let y: &f64 = &3.0
let my_fn: MyFn<f64, f64> {
call: |x| {
x + *y
}
}

我知道在这种情况下需要一个闭包,但是call的类型应该是什么,这样它才能捕获任何不可变的引用(例如函数引用)?

是否可以构建结构[…],使其能够捕获。。。?

No-捕获涉及闭包,而MyFn::call的类型是一个函数。MyFn可以通过使其类型为泛型类型或trait对象来将闭包存储在call中。

泛型是非常有效的,但使MyFn对每个闭包都有不同的类型:

struct MyFn<A, B, F: Fn(A) -> B> {
call: F,
_data: PhantomData<(A, B)>,
}
let y: f64 = 3.0;
let my_fn: MyFn<f64, f64, _> = MyFn {
call: |x| x + y,
_data: PhantomData,
};

每个闭包都有不同的类型,这意味着您将无法轻松创建具有不同闭包的MyFn向量,也无法将其存储在需要拼写类型的地方。

或者,您可以使call动态,即将其表示为特征对象。这将使MyFn仅在输入和输出类型上保持泛型,并将防止不同的闭包影响MyFn的类型。这种灵活性是以构造MyFn时的分配和调用call时的指针间接为代价的。(事先的成本远没有人们想象的那么大,但意识到这一点很好。)这样的MyFn看起来是这样的:

struct MyFn<'a, A, B> {
call: Box<dyn Fn(A) -> B + 'a>,
}
let y: f64 = 3.0;
let my_fn: MyFn<f64, f64> = MyFn {
call: Box::new(|x| x + y),
};

与通用版本相比,动态版本似乎有额外的生存期,但这是因为生存期是前一版本中未命名闭包类型的一部分。

最新更新