8.2.3 Type anonymity

클로저는 포함되어 있는 범위에서 변수를 간단명료하게 캡쳐한다. 이게 중요하냐고? 확실히 그렇다. 그들이 정의된 방법 때문에 필요한 [제네릭]을 요구하는 함수에서 클로저가 어떻게 사용되는지 살펴보자.

// `F` must be generic.
fn apply<F>(f: F) where
    F: FnOnce() {
    f()
}

클로저가 정의되면, 컴파일러는 캡쳐 된 변수를 내부에 저장하기 위해 암시적으로 새 익명 구조체를 생성하고, 그 동안 기능을 traits: Fn, FnMut, FnOnce 중에 하나로 이 알지 못하는 타입을 위해 구현한다. 이 타입은 호출되는 시점까지 변수로 할당되어 저장된다.

이 새로운 타입은 알려지지 않은 타입이므로, 함수에서 사용하고자 하면 제네릭이 필요하다. 그러나, 범위가 정해지지 않은 타입 인자 <T>는 아직 모호하고 또한 허용되지 않는다. 따라서, traits: 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);
}

See also:

A thorough analysis, Fn, FnMut, and FnOnce

results matching ""

    No results matching ""