【问题标题】:In Rust, what is `fn() -> ()`?在 Rust 中,什么是`fn() -> ()`?
【发布时间】:2020-10-10 20:59:49
【问题描述】:

我掌握了 Fn(大写-F)特征:FnFnMutFnOnce。我知道它们是特质,并且像特质一样工作。

但是fn(小写-f)呢?它在编辑器中得到了不同的颜色,这告诉我这不是一个特征。它也可以用于其他人无法使用的某些地方(反之亦然),尽管它在其他情况下的行为似乎相似。我在文档中找不到任何直接解释它的内容。

【问题讨论】:

    标签: function rust traits


    【解决方案1】:

    Rust 有 3 种类函数类型:

    1. Function items 是使用fn foo() {...} 创建函数时得到的结果。它也是类似元组的结构或枚举变体的构造函数的类型。函数项的大小为零(它们不包含数据),并且每个非泛型函数都有一个唯一的、不可命名的函数项类型。在错误消息中,编译器将这些“Voldemort 类型”显示为类似于fn() -> () {foo}(函数名称在{})。

    2. Closures 是类似于函数项的值,但闭包可能包含数据:它们从环境中捕获的任何变量的副本或引用。如您所知,您可以使用闭包语法 (|args| expression) 创建闭包。与函数项一样,闭包具有唯一的、不可命名的类型(由编译器呈现,类似于 [closure@src/main.rs:4:11: 4:23])。

    3. Function pointers 是您要问的:看起来像 fn() -> () 的类型。函数指针不能包含数据,但它们的大小不为零;顾名思义,它们是指针。函数指针可以指向函数项,也可以指向不捕获任何内容的闭包,但不能为空。

    如果可能,函数项和闭包会自动强制转换为相关的函数指针类型,这就是let f: fn(i32) = |_| (); 起作用的原因:因为闭包不捕获任何内容,所以可以将其强制转换为函数指针。

    所有三个类函数类型都实现了相关的FnFnMutFnOnce 特征(除了闭包可能不会实现FnFnMut,具体取决于它们捕获的内容)。函数项和函数指针也实现了CopyCloneSendSync(闭包仅在其所有内容都实现这些特征时才实现)。

    在性能方面,函数指针是泛型和特征对象之间的折衷。它们必须被取消引用才能被调用,因此调用函数指针可能比直接调用函数项或闭包要慢,但仍比调用 dyn Fn trait 对象快,后者除了间接调用之外还涉及 vtable 查找。但是,在实际代码中,有许多变量会混淆幼稚的分析;如果性能差异对您很重要,您应该测量它而不是猜测哪个更快。

    参考文献

    【讨论】:

      【解决方案2】:

      这是一个function pointer type

      指向一个函数,而不是一个闭包,因为它只包含函数的地址,而不是闭包所需的捕获环境。

      Fn trait(大写 F)可以指代闭包或函数。

      【讨论】:

      • 我可以将闭包转换为fn。虽然,也许这隐含地禁止它捕获任何东西。
      • @brundolf 你猜对了,一个不捕获任何东西的闭包实际上是一个函数。
      【解决方案3】:

      fn 是函数指针的类型。另请参阅文档中的此处: https://doc.rust-lang.org/std/primitive.fn.html

      【讨论】:

        猜你喜欢
        • 2021-08-19
        • 2018-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-02
        • 1970-01-01
        • 2020-06-20
        相关资源
        最近更新 更多