在学习 rust closures 时,我尝试 Like Java return "A Function"
fn equal_5<T>() -> T
where T: Fn(u32) -> bool {
let x:u32 = 5;
|z| z == x
}
但是当我使用它
let compare = equal_5();
println!("eq {}", compare(6));
构建错误
11 | let compare = equal_5();
| ------- consider giving `compare` a type
12 | println!("eq {}", compare(6));
| ^^^^^^^^^^ cannot infer type
|
= note: type must be known at this point
答案 0 :(得分:2)
见:https://doc.rust-lang.org/stable/rust-by-example/trait/impl_trait.html
目前,T
只是描述一种类型,在本例中实现了 Fn
特性。换句话说,T
不是具体类型。事实上,对于闭包,不可能声明一个具体的类型,因为每个闭包都有自己独特的类型(即使两个闭包完全相同,它们也有不同的类型。)
为了避免直接声明闭包的类型(这是不可能的),我们可以使用 impl
关键字。 impl 关键字的作用是将我们对类型(特征边界)的描述转换为符合这些边界的不可见的具体类型。
所以这是有效的:
fn equal_5() -> impl Fn(u32) -> bool {
let x:u32 = 5;
move |z| z == x
}
let compare = equal_5();
println!("eq {}", compare(6));
需要注意的一点是我们也可以动态执行此操作。使用框和 dyn
特征。因此,这也有效,但会产生与动态分辨率相关的成本。
fn equal_5() -> Box<dyn Fn(u32) -> bool> {
let x:u32 = 5;
Box::new(move |z| z == x)
}
let compare = equal_5();
println!("eq {}", compare(6));
答案 1 :(得分:1)
编译器似乎在抱怨它需要一个类型参数但找到了一个闭包。它知道类型,不需要类型参数,而且闭包对象的大小不是固定的,所以你可以使用 impl
或 Box。闭包还需要使用 move
来将存储在 x
中的数据移动到闭包本身中,否则在 equal_5()
返回后将无法访问它,并且您将获得一个x
存在的时间不够长的编译器错误。
fn equal_5() -> impl Fn(u32) -> bool {
let x:u32 = 5;
move |z| z == x
}
或
fn equal_5() -> Box<Fn(u32) -> bool> {
let x:u32 = 5;
Box::new(move |z| z == x)
}