return 个闭包但无法推断类型
return closures but cannot infer type
在学习 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
编译器似乎在抱怨它需要一个类型参数,但却找到了一个闭包。它知道类型,不需要类型参数,而且闭包对象的大小不固定,因此您可以使用 impl
或 Box。闭包还需要使用 move
以便将存储在 x
中的数据移动到闭包本身中,否则在 equal_5()
returns 之后将无法访问它,并且您会得到一个编译器错误 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)
}
参见: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));
在学习 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
编译器似乎在抱怨它需要一个类型参数,但却找到了一个闭包。它知道类型,不需要类型参数,而且闭包对象的大小不固定,因此您可以使用 impl
或 Box。闭包还需要使用 move
以便将存储在 x
中的数据移动到闭包本身中,否则在 equal_5()
returns 之后将无法访问它,并且您会得到一个编译器错误 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)
}
参见: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));