使用reikna crate动态生成被积函数遇生命周期错误的解决方法
问题:使用reikna动态生成积分函数时的生命周期错误
问题场景
我想用reikna crate计算函数积分,但动态生成待积分函数时出现异常。我的代码如下:
use reikna::integral::*; use reikna::func; fn calc(i: f64) -> f64 { let f = func!(|x| i + x); return integrate(&f, 0.0, 100.0); } fn main() { let res = calc(50.0); println!("The result is: {}", res); }
错误信息
运行后抛出以下错误:
error[E0597]: `i` does not live long enough --> src/main.rs:5:23 | 5 | let f = func!(|x| i + x); | ----------^----- | | | | | | | borrowed value does not live long enough | | value captured here | type annotation requires that `i` is borrowed for `'static` 6 | return integrate(&f, 0.0, 100.0); 7 | } | - `i` dropped here while still borrowed For more information about this error, try `rustc --explain E0597`.
问题根源(基于crate简化实现)
研究reikna的实现逻辑后,其核心简化代码如下:
pub use std::rc::Rc; pub type Function = Rc<dyn Fn(f64) -> f64>; #[macro_export] macro_rules! func { ($e:expr) => (Rc::new($e) as Function); } fn print_3_next_numbers(i: f64) { let f = func!(|x| 1.0 + x); println!("The next +1 number is: {}", f(1.0)); println!("The next +2 number is: {}", f(2.0)); println!("The next +3 number is: {}", f(3.0)); } fn main() { print_3_next_numbers(50.0); }
解决方案
问题出在func!宏生成的Function类型是Rc<dyn Fn(f64) -> f64>,这个trait对象默认要求'static生命周期。而闭包|x| i + x默认是借用i,当calc函数结束时i被销毁,闭包引用就失效了。
解决方法是让闭包捕获i的所有权,而不是借用:
use reikna::integral::*; use reikna::func; fn calc(i: f64) -> f64 { // 使用move关键字转移i的所有权到闭包中 let f = func!(move |x| i + x); integrate(&f, 0.0, 100.0) } fn main() { let res = calc(50.0); println!("The result is: {}", res); }
原理说明
move关键字会让闭包捕获变量的所有权,而非默认的借用。这样i会被移动(或复制,因为f64是Copy类型)到闭包内部,和闭包一起被包裹在Rc中,生命周期与闭包一致,满足'static的要求——只要Rc存在,i就不会被销毁。- 由于
f64是Copy类型,move操作实际是复制一份i到闭包中,不会影响原变量的后续使用(不过在这个场景中原变量i也不会再被用到)。
内容的提问来源于stack exchange,提问作者Pierre Neumann
相关产品推荐
相关产品推荐

