类型匿名

闭包可以简洁地捕获封闭作用域中的变量。这有什么影响吗?当然有。观察一下,将闭包作为函数参数使用时,需要泛型,这正是因为它们的定义方式。

#![allow(unused)]
fn main() {
// `F` must be generic.
fn apply<F>(f: F) where
    F: FnOnce() {
    f();
}
}

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

由于这个新类型是未知类型,任何在函数中的使用都需要泛型。然而,无界类型参数<T>仍然是模糊的,并且不允许。因此,通过它实现的traitFnFnMutFnOnce进行约束足以指定其类型。

// `F` must implement `Fn` for a closure which takes no
// inputs and returns nothing - exactly what is required
// for `print`.
fn apply<F>(f: F) where
    F: Fn() {
    f();
}

fn main() {
    let x = 7;

    // Capture `x` into an anonymous type and implement
    // `Fn` for it. Store it in `print`.
    let print = || println!("{}", x);

    apply(print);
}

另请参阅

深入分析FnFnMut,以及FnOnce