如果我理解正确,在 Rust 中,每个闭包类型都有一个无法写出的唯一类型。我也认为这适用于函数,但是,我能够执行以下操作,其中我在 and 的返回类型中显式编写类型get_struct_1
参数get_struct_2
:
struct FooStruct<F>
where F: Fn(i32) -> i32
{
f: F,
}
fn foo(x: i32) -> i32 {
2*x
}
fn bar(x: i32) -> i32 {
-1*x
}
fn get_struct_1() -> FooStruct<fn(i32) -> i32>
{
FooStruct { f: foo }
}
fn get_struct_2() -> FooStruct<fn(i32) -> i32>
{
FooStruct { f: bar }
}
// This does not work - the trait has to be boxed
//fn get_struct_3() -> FooStruct<Fn(i32) -> i32>
//{
// FooStruct { f: |x| 10*x }
//}
fn main() {
let mut x = get_struct_1();
// Why does this work - do bar and foo have the same type?
x = get_struct_2();
// Why does this work - doesn't a closure have its own unique, unwriteable type?
x = FooStruct { f: |x| 10*x };
let mut y = FooStruct { f: |x| 10*x };
// Does not work - no two closures have the same type.
//y = FooStruct { f: |x| 10*x };
// Does not work - even though the 'other way around' worked with x.
// But _does_ work if I type-annotate y with FooStruct<fn(i32) -> i32>
//y = get_struct_1();
}
我认为 Rust 在处理类型参数的方式上是单态的。所以如果我这样做
struct FooStruct {
f: Box<dyn Fn(i32) -> i32>
}
程序将在运行时动态确定运行哪个f
,但FooStruct<F>
版本避免了动态调度。
这个例子似乎不同意这一点。如果该x = get_struct_2();
行在if
语句中,编译器将无法确定是否x
保存了函数的包装版本foo
或bar
.