类型匿名

闭包能简洁地从外部作用域捕获变量。这会有什么影响吗?当然会有。注意观察如何将闭包作为函数参数使用时需要泛型,这是由于闭包的定义方式所决定的:

#![allow(unused)]
fn main() {
// `F` 必须是泛型
fn apply<F>(f: F) where
    F: FnOnce() {
    f();
}
}

当定义一个闭包时,编译器会隐式创建一个新的匿名结构来存储内部捕获的变量,同时通过 FnFnMutFnOnce 这些 trait 之一为这个未知类型实现功能。这个类型被赋给变量并存储,直到被调用。

由于这个新类型是未知类型,在函数中使用时就需要泛型。然而,一个无界的类型参数 <T> 仍然会是模糊的,不被允许。因此,通过 FnFnMutFnOnce 这些 trait 之一(它实现的)来约束就足以指定其类型。

// `F` 必须实现 `Fn` 用于一个不接受输入且不返回任何内容的闭包
// - 这正是 `print` 所需要的
fn apply<F>(f: F) where
    F: Fn() {
    f();
}

fn main() {
    let x = 7;

    // 将 `x` 捕获到一个匿名类型中并为其实现 `Fn`
    // 将其存储在 `print` 中
    let print = || println!("{}", x);

    apply(print);
}

另请参阅:

深入分析FnFnMutFnOnce