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