返回闭包但无法推断类型

时间:2021-06-12 02:01:23

标签: rust closures

在学习 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

2 个答案:

答案 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)
}