【发布时间】:2019-03-07 06:05:29
【问题描述】:
从问题的公认答案来看,递归闭包的方法不适合我:
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));
}
上面的代码运行良好。
但是我的闭包需要从函数中返回,所以不能作为引用防止悬空引用,而且我们从编译时也不知道闭包的大小,所以我使用了智能指针@987654324 @ 为了它。下面的代码会报错:
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
【问题讨论】:
-
“我的闭包需要从函数中返回,并且需要从环境中捕获变量。” ——这两个要求是互不相容的,因为环境的寿命不够长。无论是另一个闭包还是实现
Fn的显式结构,您都必须将环境包装在返回函数的一部分中。 -
@JanHudec 不,只需将变量的所有权从环境移动到闭包使用
move | | {}语法,然后它就可以工作了。 -
但不是从环境中捕获,而是移入了闭包。那是不同的事情。
标签: rust