如何返回接收lambda/函数的匿名函数/lambda?
可以使用lambda和函数创建有序对(Lisp中的cons),如中所示 它也适用于Python:如何返回接收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
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)来谈论它们。通常,有两种方法可以接受实现traitFoo
的任意类型:使用静态分派和单组化(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)来谈论它们。通常,有两种方法可以接受实现traitFoo
的任意类型:使用静态分派和单组化(fn-bar(x:T)
)或作为trait对象和使用动态分派(fn-bar(x:&Foo)
)。但是,您已经返回了一个trait对象(Box
),并且trait对象不能有泛型方法(由于各种原因,它们不能是单形态的)。这意味着您需要自己接受一个trait对象,因为trait对象没有大小,所以它们需要隐藏在引用或类似于Box
的东西后面
闭包不会返回任何东西!正确,因为这同样需要单晶化,因为锈菌是静态类型。您展示/链接的示例是动态类型化语言,这样的事情不成问题。在《铁锈》中,这是一个不同的故事。你可以用Rust之类的东西来伪造动态输入。但这并不是真正的习惯用法,应该避免。也许你真的需要它,但也许你也想在Rust中错误地使用其他语言的模式,而应该用一种更为生疏的方式来思考你的问题;-)