简体   繁体   English

递归关闭作为函数参数“由于需求冲突而无法推断出适当的寿命”

[英]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: 首先,您必须了解它们之间的区别:

  1. fn(A) -> B
  2. impl Fn(A) -> B or T: Fn(A) -> B impl Fn(A) -> BT: Fn(A) -> B
  3. &dyn Fn(A) -> B
  4. 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用作fA参数。 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.

相关问题 作为函数参数的闭包“由于需求冲突而无法推断出适当的寿命” - Closure as function parameter “cannot infer an appropriate lifetime due to conflicting requirements” 由于递归结构中的冲突要求,无法推断出适当的生命周期 - Cannot infer an appropriate lifetime due to conflicting requirements in a recursive struct "由于要求冲突,无法推断函数调用中生命周期参数 &#39;_ 的适当生命周期" - cannot infer an appropriate lifetime for lifetime parameter '_ in function call due to conflicting requirements 由于需求冲突,无法推断出合适的生命周期 - Cannot infer an appropriate lifetime due to conflicting requirements 匿名函数 - 由于需求冲突,无法推断出合适的生命周期 - Anonymous function - cannot infer an appropriate lifetime due to conflicting requirements 将结构转换为具有生存期的特征得到“由于需求冲突,无法为生存期参数&#39;a&#39;推断适当的生存期” - casting struct to trait with lifetime got “cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements” 由于对由具有 Serde Deserialize 的枚举组成的结构的要求相互冲突,因此无法为生命周期参数“de”推断合适的生命周期 - cannot infer an appropriate lifetime for lifetime parameter `'de` due to conflicting requirements for struct made of enums with Serde Deserialize 创建引用错误的递归列表“由于要求冲突,无法推断 autoref 的适当生命周期” - Creating a recursive list of references errors with "cannot infer an appropriate lifetime for autoref due to conflicting requirements" 由于需求冲突,无法为 autoref 推断适当的生命周期 - Cannot infer an appropriate lifetime for autoref due to conflicting requirements Rust:由于要求冲突,无法推断 autoref 的适当生命周期 - Rust: cannot infer an appropriate lifetime for autoref due to conflicting requirements
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM