Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Анонімність типу

Замикання стисло захоплюють змінні з охоплюючих областей видимості. Чи має це якісь наслідки? Безумовно, має. Зверніть увагу, що використання замикання як параметра функції потребує [узагальнень], що необхідно через те, як вони визначені:

#![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