Анонимность типа
Замыкания кратко захватывают переменные из окружающих областей. Это имеет какие-то последствия? Конечно, имеет. Посмотрите, как использование замыкания в качестве параметра функции требует [обобщений], что необходимо из-за того, как они определены:
// `F` должен быть обобщенным.
fn apply<F>(f: F) where
F: FnOnce() {
f();
}
Когда определяется замыкание, компилятор неявно создает новую анонимную структуру для хранения захваченных переменных внутри, в то же время реализуя функциональность с помощью одного из трейтов
: Fn
, FnMut
или FnOnce
для этого неизвестного типа. Этот тип назначается переменной, которая хранится до вызова.
Поскольку этот новый тип имеет неизвестный тип, любое использование в функции будет требовать обобщений. Однако, неограниченный параметр типа <T>
по-прежнему будет неоднозначным и не будет допускаться. Таким образом, ограничение одним из трейтов
: Fn
, FnMut
или FnOnce
(который он реализует) достаточно для указания его типа.
// `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);
}