返回一个递归闭包,它将环境可变变量从函数移动到其中?



从问题的公认答案来看,递归闭包的方法不适合我:

是否可以在 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)
})
}

最新更新