Анонімність типу
Замикання стисло захоплюють змінні з охоплюючих областей видимості. Чи має це якісь наслідки? Безумовно, має. Зверніть увагу, що використання замикання як параметра функції потребує [узагальнень], що необхідно через те, як вони визначені:
#![allow(unused)]
fn main() {
// `F` must be generic.
fn apply<F>(f: F) where
F: FnOnce() {
f();
}
}
Коли замикання визначається, компілятор неявно створює нову анонімну
структуру для зберігання захоплених змінних всередині, водночас
реалізуючи функціональність через один із traits: Fn, FnMut або
FnOnce для цього невідомого типу. Цей тип призначається змінній, яка
зберігається до виклику.
Оскільки цей новий тип є невідомим типом, будь-яке використання у функції вимагатиме
узагальнень. Однак необмежений параметр типу <T> усе одно був би неоднозначним
і не був би дозволений. Отже, обмеження одним із traits: Fn, FnMut або
FnOnce (який він реалізує) є достатнім, щоб визначити його тип.
// `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);
}
Див. також:
Ґрунтовний аналіз, Fn, FnMut,
та FnOnce