从问题的公认答案来看,进行递归关闭的方式不适合我:
Is it possible to make a recursive closure in Rust?
我的闭包需要从一个函数返回,并且需要将变量从环境移入它,并且可以对其进行突变。
然后我发现一种方法似乎更适合我:
Anonymous recursion with closures
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));
}
上面的代码工作正常。
但是我的闭包需要从一个函数中返回,因此它不能作为防止悬空的Reference的引用,并且我们从编译时就不知道闭包的大小,因此我使用了智能指针{{ 1}}。下面的代码抛出错误:
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));
}
答案 0 :(得分:1)
您可以将递归上下文包装在非递归闭包中:
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)
})
}