【问题标题】:When does a closure implement Fn, FnMut and FnOnce?闭包何时实现 Fn、FnMut 和 FnOnce?
【发布时间】:2015-07-22 12:45:22
【问题描述】:

闭包实现FnFnMutFnOnce特征的具体条件是什么?

即:

  • 闭包何时实现FnOnce trait?
  • 闭包何时实现FnMut trait?
  • 闭包何时实现Fn trait?

例如,改变其主体上的闭包状态会使编译器无法在其上实现Fn

【问题讨论】:

标签: rust closures


【解决方案1】:

每个特征都代表了越来越多的关于闭包/函数的限制性属性,由它们的 call_... 方法的签名指示,特别是 self 的类型:

  • FnOnce (self) 是可以调用一次的函数
  • FnMut (&mut self) 是可以在具有 &mut 对其环境的访问权限时调用的函数
  • Fn (&self) 是只有 & 对其环境具有访问权限时才能调用的函数

闭包|...| ... 将自动实现尽可能多的那些。

  • 所有闭包都实现FnOnce:一个不能被调用一次的闭包不值得这个名字。请注意,如果闭包仅实现FnOnce,则只能调用一次。
  • 未移出其捕获的闭包实现FnMut,允许多次调用它们(如果对函数对象存在非别名访问)。
  • 不需要对其捕获进行唯一/可变访问的闭包实现Fn,允许它们基本上在任何地方被调用。

这些限制直接来自self 的类型以及将闭包“脱糖”到结构中;在我的博文Finding Closure in Rust中描述。

有关闭包的信息,请参阅 Rust 编程语言中的 Closures: Anonymous Functions that Can Capture Their Environment

【讨论】:

  • 如果一个闭包只实现了FnOnce,是不是意味着只能调用一次呢?
  • 我误读了 nalply 的评论,这让我有些困惑。未来的读者,请注意他说“如果闭包only实现FnOnce”。
  • 实现细节:将尽可能多地自动实现。 并不完全正确,如果需要,它会自动实现它们。您可以使用特化检测用于 FnMut 参数的闭包丢失的 Fn-impl。这是错误github.com/rust-lang/rust/issues/26085
  • 我仍然很难理解所有闭包如何实现FnOnce,即使它们可以被多次调用。此特征的名称令人困惑。
  • 几种思考方式: 1. FnOnce 中的“Once”是指调用者调用它的次数上限,而不是它可以调用多少次 被调用。 2. 你总是可以将一个可以被多次调用的闭包转换成一个只能被调用一次的闭包:只需在第一次调用后丢弃与闭包相关的所有内存。但是你不能以其他方式将其转换回来。
猜你喜欢
  • 1970-01-01
  • 2022-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 2023-01-14
  • 2019-12-22
相关资源
最近更新 更多