如何返回接收lambda/函数的匿名函数/lambda?

如何返回接收lambda/函数的匿名函数/lambda?,lambda,rust,closures,Lambda,Rust,Closures,可以使用lambda和函数创建有序对(Lisp中的cons),如中所示 它也适用于Python: def cons(x,y): 返回λm:m(x,y) def汽车(z): 返回z(λx,y:x) def cdr(z): 返回z(λx,y:y) 当我在Rust(一种静态类型语言)中实现它时: fn cons(x: i32, y: i32) -> Box<Fn() -> Fn(i32, i32)> { Box::new(move |m| m(x, y)); } f

可以使用lambda和函数创建有序对(Lisp中的cons),如中所示

它也适用于Python:

def cons(x,y):
返回λm:m(x,y)
def汽车(z):
返回z(λx,y:x)
def cdr(z):
返回z(λx,y:y)
当我在Rust(一种静态类型语言)中实现它时:

fn cons(x: i32, y: i32) -> Box<Fn() -> Fn(i32, i32)> {
    Box::new(move |m| m(x, y));
}
fn cons(x:i32,y:i32)->框fn(i32,i32)>{
盒子:新的(移动| m | m(x,y));
}
它显示了错误:

错误:此值的类型在此上下文中必须是已知的
-->src/main.rs:2:23
|
2 |盒子:新的(移动| m | m(x,y));
|                       ^^^^^^^
错误[E0308]:类型不匹配
-->src/main.rs:1:54
|
1 | fn cons(x:i32,y:i32)->框fn(i32,i32)>{
|从这里开始。。。
2 | |盒::新(移动| m | m(x,y));
3 | | }
|| u^…结束于此:预期框,找到()
|
=注意:预期类型为'Box std::ops::Fn(i32,i32)+'static+'static>`
=注意:找到类型“()`

如何定义
m
的类型?

第一个小错误:在函数体的末尾添加了分号。这意味着

Box::new(move |m|m(x,y));
只是一句没有副作用的话,很像
3+4。当删除分号时,会出现更好的编译器错误,因为现在编译器开始将表达式类型与返回类型连接起来

说到这里:很遗憾,您的返回类型是错误的。您需要的是捕获两个参数
x
y
,并返回一个闭包,该闭包接受另一个闭包,然后用这两个参数调用该闭包。此代码适用于:

fn cons(x: i32, y: i32) ->  Box<Fn(&Fn(i32, i32))> {
    Box::new(move |m| m(x, y))
}
但我们有两个问题:

  • 为什么引用
    &
    ?Rust中的闭包是伏地魔类型的闭包,你只能根据它们实现的特性(例如
    Fn
    trait)来谈论它们。通常,有两种方法可以接受实现trait
    Foo
    的任意类型:使用静态分派和单组化(
    fn-bar(x:T)
    )或作为trait对象和使用动态分派(
    fn-bar(x:&Foo)
    )。但是,您已经返回了一个trait对象(
    Box
    ),并且trait对象不能有泛型方法(由于各种原因,它们不能是单形态的)。这意味着您需要自己接受一个trait对象,因为trait对象没有大小,所以它们需要隐藏在引用或类似于
    Box
    的东西后面

  • 闭包不会返回任何东西!正确,因为这同样需要单晶化,因为锈菌是静态类型。您展示/链接的示例是动态类型化语言,这样的事情不成问题。在《铁锈》中,这是一个不同的故事。你可以用Rust之类的东西来伪造动态输入。但这并不是真正的习惯用法,应该避免。也许你真的需要它,但也许你也想在Rust中错误地使用其他语言的模式,而应该用一种更为生疏的方式来思考你的问题;-)


  • 第一个小错误:在函数体的末尾添加了分号。这意味着

    Box::new(move |m|m(x,y));
    
    只是一句没有副作用的话,很像
    3+4。当删除分号时,会出现更好的编译器错误,因为现在编译器开始将表达式类型与返回类型连接起来

    说到这里:很遗憾,您的返回类型是错误的。您需要的是捕获两个参数
    x
    y
    ,并返回一个闭包,该闭包接受另一个闭包,然后用这两个参数调用该闭包。此代码适用于:

    fn cons(x: i32, y: i32) ->  Box<Fn(&Fn(i32, i32))> {
        Box::new(move |m| m(x, y))
    }
    
    但我们有两个问题:

  • 为什么引用
    &
    ?Rust中的闭包是伏地魔类型的闭包,你只能根据它们实现的特性(例如
    Fn
    trait)来谈论它们。通常,有两种方法可以接受实现trait
    Foo
    的任意类型:使用静态分派和单组化(
    fn-bar(x:T)
    )或作为trait对象和使用动态分派(
    fn-bar(x:&Foo)
    )。但是,您已经返回了一个trait对象(
    Box
    ),并且trait对象不能有泛型方法(由于各种原因,它们不能是单形态的)。这意味着您需要自己接受一个trait对象,因为trait对象没有大小,所以它们需要隐藏在引用或类似于
    Box
    的东西后面

  • 闭包不会返回任何东西!正确,因为这同样需要单晶化,因为锈菌是静态类型。您展示/链接的示例是动态类型化语言,这样的事情不成问题。在《铁锈》中,这是一个不同的故事。你可以用Rust之类的东西来伪造动态输入。但这并不是真正的习惯用法,应该避免。也许你真的需要它,但也许你也想在Rust中错误地使用其他语言的模式,而应该用一种更为生疏的方式来思考你的问题;-)