0

如果我理解正确,在 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保存了函数的包装版本foobar.

4

1 回答 1

4

闭包(以及与此相关的函数)确实具有独特的、不可写的类型。但是,当它们不捕获任何变量时,它们也可以(并且也隐式地*)转换为函数指针,而您的则没有。这基本上是它起作用的原因:

fn main() {
    // closure is inferred to be a function pointer
    let mut f: fn() -> i32 = || 5;
    // assigning a different function pointer
    f = || 6;
}

但这不会:

fn main() {
    // closure is inferred to be a unique closure type
    let mut f = || 5;
    // uh oh! different closure type, errors
    f = || 6;
}

* 与其说是隐式转换,不如说是隐式类型推断

于 2021-11-13T02:56:22.787 回答