Rust 递归闭包作为函数参数“;由于需求冲突”;

Rust 递归闭包作为函数参数“;由于需求冲突”;,rust,Rust,这个问题比你想象的要复杂得多 有一个递归闭包,将环境变量移入其中 下面的代码是一个有用的函数集,用于函数编程,包括: 我想知道是否可以将该闭包传递给函数,然后在该闭包中调用该函数,下面的代码会抛出一个错误 extern crate tool; use tool::prelude::*; use std::cell::RefCell; fn main() { let a = RefCell::new(false); let fib = fix(move |f, x| {

这个问题比你想象的要复杂得多

有一个递归闭包,将环境变量移入其中

下面的代码是一个有用的函数集,用于函数编程,包括:

我想知道是否可以将该闭包传递给函数,然后在该闭包中调用该函数,下面的代码会抛出一个错误

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));
}
外部板条箱工具;
使用工具::前奏::*;
使用std::cell::RefCell;
fn main(){
设a=RefCell::new(false);
设fib=fix(移动| f,x |{
*a、 借用_mut()=真;
如果x==0 | | x==1{
x
}否则{
//'f'是'fib`
b(盒子:新的(f),x-1)+f(x-2)
}
});
fn b(c:Box u64>,n:u64)->u64{
c(n)
}
println!(“{}”,b(Box::new(fib),10));
}
错误[E0495]:由于需求冲突,无法推断适当的生存期
-->src/main.rs:14:24
|
14 | b(盒子:新的(f),x-1)+f(x-2)
|                        ^
|
注意:首先,生命周期不能超过8:19在身体上定义的匿名生命周期#2。。。
-->src/main.rs:8:19
|
8 |让fib=固定(移动| f,x |{
|  ___________________^
9 | |*a.借用_mut()=真;
10 | |如果x==0 | | x==1{
11 | | x
...  |
15 | |         }
16 | |     });
| |_____^
=注意:…因此表达式是可赋值的:
预期&dyn标准::操作::Fn(u64)->u64
已找到&dyn std::ops::Fn(u64)->u64
=注意:但是,生存期必须对静态生存期有效。。。
=注意:…因此表达式是可赋值的:
应为std::boxed::Box u64+‘静态)>
找到std::boxed::Box u64>

看起来您在这里混合了几个概念。首先,您必须了解以下各项之间的区别:

  • fn(A)->B
  • impl-Fn(A)->B
    T:Fn(A)->B
  • &dyn Fn(A)->B
  • 框B>
  • 数字1是指向函数的指针类型,就像在C中一样

    数字2是实现函数trait
    Fn
    的泛型类型,该类型是可调用的

    数字3是对可调用对象的动态引用(
    dyn
    关键字是可选的)

    数字4是一个trait对象,它是一个实类型为erased的装箱可调用对象

    现在看一下以下定义:


    似乎对我有用。这就是你想要的吗?这对我也有用。但我发现我需要的东西比它还复杂。我不知道我是需要休息一下,还是继续问问题。我刚开始生锈,我很累。我想要的是:看起来你在混合
    fn
    dyn-fn
    ,也许还有
    impl-fn
    。我不熟悉
    工具
    ,但会胡闹,编译。我很快就会学会的,嗨,我刚在你帮我的时候改变了要点。请您再检查一下:在您的第一条评论中,我没有看到任何动态引用,
    fnb(c:impl-fn(u64)->u64,n:u64)
    刚刚成功,为什么@周汉成: 啊,但是注释中的代码确实有一个动态引用。您看不到它,因为类型是由编译器推导出来的:lambda函数中的
    f
    参数。如果您检查其类型,则它是
    &dyn-Fn()->\u
    。这是意料之中的,因为这正是
    fix()
    所需要的。
    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));
    }
    
    pub fn fix<A, B, F>(f: F) -> impl Fn(A) -> B 
    where
        F: Fn(&Fn(A) -> B, A) -> B, 
    
    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));
    }