此问题已在此处有答案:
Is there any way to explicitly write the type of a closure?(2个答案)
7天前关闭
考虑到这段有效的Rust代码
fn f(pt: &[f64 ; 3]) -> f64 {
pt[0] + pt[1] + pt[2]
}
fn main(){
let f1d_array: [_; 3] = std::array::from_fn(|dir| {
move |pt: [f64; 3]| {
move |x: f64| -> f64 {
let mut pt_new = pt;
pt_new[dir] = x;
f(&pt_new)
}
}
});
let pt = [0., 1., 2.];
let f1d_0 = f1d_array[0](pt);
assert_eq!(f1d_0(0.),3.);
assert_eq!(f1d_0(1.),4.);
let f1d_1 = f1d_array[1](pt);
assert_eq!(f1d_1(0.),2.);
assert_eq!(f1d_1(1.),3.);
let f1d_2 = f1d_array[2](pt);
assert_eq!(f1d_2(0.),1.);
assert_eq!(f1d_2(1.),2.);
}
变量f1d_array
的类型是什么?我需要知道它,以便正确定义一个使用f1d_array
类型作为输入参数的函数。
这里是Rust playground的链接:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=cabc0d9a5f496e3da0b467b9c46f2535
2条答案
按热度按时间atmip9wb1#
你可以只写let the compiler tell you,它是
[[closure@main.rs:9:9]; 3]
,但你不能命名这个类型。所以要创建一个以闭包为参数的函数,你必须求助于泛型:
Playground
pengsaosao2#
@cafce25的答案是正确的;该类型当前不可命名。由于您可能希望您的函数采用任何“类似”闭包的类型,因此在接受闭包时,泛型是大多数情况下的方法。
然而,如果你确定你只需要函数接受你的闭包类型,而不是其他类型,有一种方法可以在unstable rust中命名它的类型:
(Playground)
这使用了
type_alias_impl_trait
特性,该特性允许您通过指定类型的属性来为类型(即使是没有任何名称的类型,例如闭包)给予另一个名称。这与泛型非常相似,但方向相反。当在函数中使用泛型时,它本质上是在说“我接受任何具有这些属性的值”。但是,当使用这些类型别名时,函数会说:“存在具有这些属性的类型,我可以接受它且只能接受它**”。
它类似于
fn(value: impl Trait)
和fn() -> impl Trait
之间的区别。fn() -> impl Trait
和type = impl Trait
都定义了所谓的存在类型。即存在的类型,但你不想/不能通过它们的实际名称引用它们,只能通过它们的属性引用它们。然而,这里有一个陷阱。注意到我说“存在一个类型”了吗?使用类型别名时,必须在某个地方使用别名,以便编译器知道实际的基础类型是什么。如果你不这样做,编译器会对你大喊:
然而,总而言之,这些通常在返回值时使用,而不是在接受值时使用。由于您不能创建
fn() -> impl Fn() -> impl Fn()
,因此可以使用以下解决方案,因为您可以定义fn() -> F; type F = impl Fn() -> G; type G = impl Fn();
。可能存在接受存在类型的用例,例如不能接受泛型的FFI函数。