2017-03-05 41 views
0

它可以创建一个有序对使用Lambda和功能(在Lisp的利弊),如图Use of lambda for cons/car/cdr definition in SICP如何返回接收lambda/function的匿名函数/ lambda?

它也可以在Python:

def cons(x,y): 
    return lambda m:m(x,y) 
def car(z): 
    return z(lambda x, y: x) 
def cdr(z): 
    return z(lambda x, y: y) 

当我实现它的锈,这是一种静态类型语言:

fn cons(x: i32, y: i32) -> Box<Fn() -> Fn(i32, i32)> { 
    Box::new(move |m| m(x, y)); 
} 

它显示了错误:

error: the type of this value must be known in this context 
--> src/main.rs:2:23 
    | 
2 |  Box::new(move |m| m(x, y)); 
    |      ^^^^^^^ 

error[E0308]: mismatched types 
--> src/main.rs:1:54 
    | 
1 | fn cons(x: i32, y: i32) -> Box<Fn() -> Fn(i32, i32)> { 
    | ______________________________________________________^ starting here... 
2 | |  Box::new(move |m| m(x, y)); 
3 | | } 
    | |_^ ...ending here: expected box, found() 
    | 
    = note: expected type `Box<std::ops::Fn() -> std::ops::Fn(i32, i32) + 'static + 'static>` 
    = note: found type `()` 

如何定义m的类型?

回答

2

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

Box::new(move |m|m(x,y)); 

仅仅是没有副作用的声明,就像3 + 4;。当你删除分号时,你会得到一个更好的编译器错误,因为现在编译器开始将你的表达式类型与返回类型连接起来。

说起来:不幸的是,你的返回类型是错误的。你想要的是捕获两个参数xy并返回一个闭包,它接受另一个闭包,然后用这两个参数调用闭包。此代码的工作:

fn cons(x: i32, y: i32) -> Box<Fn(&Fn(i32, i32))> { 
    Box::new(move |m| m(x, y)) 
} 

正如你可以看到,返回的封闭的类型是:Fn(&Fn(i32, i32))。关闭接受另一个关闭作为参数。您可以使用它像这样:

let fun = cons(3, 7); 
fun(&|x, y| println!("{}", x)); 

但是我们这里有两个问题:

  1. 为什么参考&? Rust中的封锁是Voldemort类型,你只能根据它们实现的特征来谈论它们(例如Fn特征)。通常,您有两种方法可以接受任意类型的实现特征Foo:具有静态调度和单态化(fn bar<T: Foo>(x: T))或特征对象和动态调度(fn bar(x: &Foo))。但是,您已经返回特质对象(Box<Fn(...)>),特质对象不能有泛型方法(由于各种原因,它们不能单形化)。这意味着您需要需要才能自己接受特质对象,并且由于特征对象未定义,它们需要隐藏在参考之后或类似Box之类的东西。

  2. 关闭不返回任何东西!正确,因为这再次需要单态化,因为Rust是静态类型的。你展示/链接的例子是动态类型语言,类似这样的东西不是问题。在鲁斯特,这是一个不同的故事。你可以假使用Box<Any>或类似的东西在Rust中输入动态。但这不是真正的习惯,应该避免。也许你真的需要它,但也许也希望正确使用其他语言模式的锈,而应该认为你的问题;-)

更生锈的方法