类型匿名

闭包从封闭的作用中域捕获变量简单明了。这样会有某些后果吗?当然会。观察一下使用闭包作为函数参量的方式是要求为泛型的,它们定义的方式决定了这是必要的(原文:Observe how using a closure as a function parameter requires generics, which is necessary because of how they are defined):

  1. // `F` 必须是泛型。
  2. fn apply<F>(f: F) where
  3. F: FnOnce() {
  4. f();
  5. }

当定义一个闭包时,编译器将隐式地创建一个新的匿名结构体来存储内部的捕获变量,
同时针对此未知类型通过其中的一种 traitFnFnMut,或 FnOnce 来实现功能
(原文:implementing the functionality via one of the traits: Fn, FnMut,
or FnOnce for this unknown type)。这个类型被赋给所存储的变量直到调用(原文:
This type is assigned to the variable which is stored until calling)。

由于这个新类型是未知的类型,所以在函数中的任何用法都要求是泛型。然而,
未限定的类型参量 <T> 仍然是不明确的并且是不允许的。因此通过其中一种
traitFnFnMut,或 RnOnce(已经实现)就足以指明它的类型。

  1. // `F` 必须针对一个没有输入参数和返回值的闭包实现 `Fn`
  2. // —— 确切地讲是 `print` 要求的类型。
  3. fn apply<F>(f: F) where
  4. F: Fn() {
  5. f();
  6. }
  7. fn main() {
  8. let x = 7;
  9. // 捕获的 `x` 成为一个匿名类型并为它实现 `Fn`。
  10. // 将它存储到 `print` 中。
  11. let print = || println!("{}", x);
  12. apply(print);
  13. }

参见:

透彻分析, Fn, FnMut,
FnOnce