rust - 返回一个递归闭包,它将环境可变变量从函数移入其中?
问题描述
从问题的公认答案来看,递归关闭的方法不适合我:
我的闭包需要从函数返回,并且需要将变量从环境移动到其中,并且可以对其进行变异。
然后我发现一种方式似乎更适合我:
use std::cell::RefCell;
fn main() {
let id = &(|a| a) as &Fn(u64) -> u64;
let (fib, fib_p): (_, RefCell<&Fn(u64) -> u64>);
fib_p = RefCell::new(id);
fib = |n: u64| {
if n < 2 {
n
} else {
(fib_p.borrow())(n - 2) + (fib_p.borrow())(n - 1)
}
};
*fib_p.borrow_mut() = &fib;
println!("{}", fib(10));
}
上面的代码工作正常。
但是我的闭包需要从函数中返回,所以不能作为引用防止悬空引用,而且我们从编译时也不知道闭包的大小,所以我使用了智能指针Box
。下面的代码抛出一个错误:
use std::cell::RefCell;
fn main() {
let id: Box<Fn(u64) -> u64> = Box::new(|a| a);
let (fib, fib_p): (Box<Fn(u64) -> u64>, RefCell<&Box<Fn(u64) -> u64>>);
fib_p = RefCell::new(&id);
fib = Box::new(|n: u64| {
if n < 2 {
n
} else {
(fib_p.borrow())(n - 2) + (fib_p.borrow())(n - 1)
}
});
*fib_p.borrow_mut() = &fib;
println!("{}", fib(10));
}
error[E0597]: `fib_p` does not live long enough
--> src/main.rs:12:15
|
8 | fib = Box::new(|n: u64| {
| -------- capture occurs here
...
12 | (&fib_p.borrow())(n - 2) + (&fib_p.borrow())(n - 1)
| ^^^^^ borrowed value does not live long enough
...
19 | }
| - borrowed value dropped before borrower
|
= note: values in a scope are dropped in the opposite order they are created
解决方案
您可以将递归上下文包装在非递归闭包中:
pub fn fib() -> Box<Fn(u64) -> u64> {
Box::new(|n: u64| {
let id = &(|a| a) as &Fn(u64) -> u64;
let (fib, fib_p): (_, RefCell<&Fn(u64) -> u64>);
fib_p = RefCell::new(id);
fib = |n: u64| {
if n < 2 {
n
} else {
(fib_p.borrow())(n - 2) + (fib_p.borrow())(n - 1)
}
};
*fib_p.borrow_mut() = &fib;
fib(n)
})
}
推荐阅读
- sql - 在 SQL Server 中选择 3 个或更多重复行
- python-3.x - 打印 div 标签 selenium python3 中的所有内容
- c# - 从 ParentViewModel 到子用户控件的 WPF 绑定不起作用
- php - 如何在 Laravel 中的 SELECT 语句后插入记录时应用“ON CONFLICT”条件?
- c# - Adding a bitmap image from list to a list
- c++ - notify_one 没有在动态库中触发 condition_variable
- angular - 如何将角度属性绑定到模型作为数组?
- c++ - OpenAcc 标准中内核和并行指令的区别
- html - 3*30% div 不会垂直居中,也不适合 100% parent-div
- reactjs - 从第二屏到第一屏获取联系人并列出它反应原生