[英]Recursive closure as function parameter “cannot infer an appropriate lifetime due to conflicting requirements”
This question is more complex than Closure as function parameter “cannot infer an appropriate lifetime due to conflicting requirements” . 这个问题比闭包更复杂, 因为函数参数“由于需求冲突而无法推断出适当的寿命” 。
There's a recursive closure which move environmental variable into it. 有一个递归的闭包将环境变量移入其中。
The code below works, tool is a grab-bag of useful functions for functional programming includes making recursive closure : 下面的代码有效,该工具是用于函数式编程的有用功能的抓包,其中包括进行递归关闭 :
extern crate tool;
use tool::prelude::*;
use std::cell::Cell;
fn main() {
let a = Cell::new(false);
let fib = fix(move |f, x| {
a.set(true);
if x == 0 || x == 1 {
x
} else {
// `f` is `fib`
f(x - 1) + f(x - 2)
}
});
println!("{}", fib(10));
}
I want to know is it possible to pass that closure to a function, then call that function in that closure, the code below throws an error. 我想知道是否有可能将该闭包传递给函数,然后在该闭包中调用该函数,下面的代码将引发错误。
extern crate tool;
use tool::prelude::*;
use std::cell::RefCell;
fn main() {
let a = RefCell::new(false);
let fib = fix(move |f, x| {
*a.borrow_mut() = true;
if x == 0 || x == 1 {
x
} else {
// `f` is `fib`
b(Box::new(f), x - 1) + f(x - 2)
}
});
fn b (c: Box<Fn(u64) -> u64>, n: u64) -> u64 {
c(n)
}
println!("{}", b(Box::new(fib), 10));
}
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:14:24
|
14 | b(Box::new(f), x - 1) + f(x - 2)
| ^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 8:19...
--> src/main.rs:8:19
|
8 | let fib = fix(move |f, x| {
| ___________________^
9 | | *a.borrow_mut() = true;
10 | | if x == 0 || x == 1 {
11 | | x
... |
15 | | }
16 | | });
| |_____^
= note: ...so that the expression is assignable:
expected &dyn std::ops::Fn(u64) -> u64
found &dyn std::ops::Fn(u64) -> u64
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn std::ops::Fn(u64) -> u64 + 'static)>
found std::boxed::Box<dyn std::ops::Fn(u64) -> u64>
It looks like you are mixing several concepts here. 您似乎在这里混几个概念。 First of all you must understand the difference between these:
首先,您必须了解它们之间的区别:
fn(A) -> B
impl Fn(A) -> B
or T: Fn(A) -> B
impl Fn(A) -> B
或T: Fn(A) -> B
&dyn Fn(A) -> B
Box<dyn Fn(A) -> B>
Number 1 is the type of a pointer to a function, just like in C. 就像C中一样,数字1是指向函数的指针的类型。
Number 2 is a generic type that implements the function trait Fn
, that is a type that is callable . 数字2是实现函数特征
Fn
的泛型类型,即可以调用的类型。
Number 3 is a dynamic reference to a callable object (the dyn
keyword is optional). 数字3是对可调用对象的动态引用(
dyn
关键字是可选的)。
Number 4 is a trait object , that is a boxed callable object with the real type erased. 数字4是特征对象 ,它是装箱的可调用对象,其中实型已删除。
Now look at the definition of tool::fix
: 现在来看一下
tool::fix
的定义:
pub fn fix<A, B, F>(f: F) -> impl Fn(A) -> B
where
F: Fn(&Fn(A) -> B, A) -> B,
From that you see that fix
uses number 2 for the f
parameter, but number 3 for the A
parameter of f
. 从中可以看到,
fix
将2用作f
参数,将3用作f
的A
参数。 Also, it returns number 2. 而且,它返回数字2。
The tricky part here is that f
is a function that takes a function as argument. 这里最棘手的部分是
f
是一个以函数为参数的函数。 The f
itself can be any of any kind that implements Fn
, but the first argument of that function must be of &dyn Fn
kind. f
本身可以是实现Fn
的任何类型,但该函数的第一个参数必须为&dyn Fn
类型。
Your original error comes from trying to box a &dyn Fn(A) -> B
, but you cannot do that generically, because such a value may contain references, and Box
requires a 'static
type. 您最初的错误来自尝试对
&dyn Fn(A) -> B
进行装箱,但是您不能一般地这样做,因为这样的值可能包含引用,并且Box
需要使用'static
类型”。
But with all that in mind you can carefully write your function without using Box
, so your problem just disappears, and the result is nicer ( playground ): 但是考虑到所有这些,您可以在不使用
Box
情况下仔细地编写函数,因此您的问题就消失了,结果更好了( 操场上 ):
fn main() {
fn wrap (wrap_fn: impl Fn(&dyn Fn(u64) -> u64, u64) -> u64) -> impl Fn(u64) -> u64 {
let a = RefCell::new(false);
let fib = fix(move |f, x| {
*a.borrow_mut() = true;
if x == 0 || x == 1 {
x
} else {
// `f` is `fib`
wrap_fn(f, x - 1) + wrap_fn(f, x - 2)
}
});
fib
}
fn b (c: &dyn Fn(u64) -> u64, n: u64) -> u64 {
c(n)
}
println!("{}", (wrap(b))(10));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.