8.2.2 As input parameters

Rust는 대부분 타입 주해 없이 즉각적으로 변수를 어떻게 캡쳐할 지를 정하게 되지만, 이 모호성은 함수를 작성할 때는 허용되지 않는다. 클로저를 입력 매개 변수로 취할 때, 클로저의 전체 타입은 몇 가지 trait들을 사용하여 주해된다. 제약이 적은 순서대로, 다음과 같다:

  • Fn: 클로저는 참조로 획득 (&T)
  • FnMut: 클로저는 가변참조로 획득 (&mut T)
  • FnOnce: 클로저는 값으로 획득 (T)

가변 변수에 기초하여 컴파일러는 가능한한 최소한의 제한적인 방법으로 변수를 캡쳐 할 것이다.

예를 들어, 매개 변수를 FnOnce로 생각해보자. 이것은 클로저가 아마도 &T, &mut T, 혹은 T로 캡쳐할 수 있음을 나타내지만 궁극적으로는 컴파일러가 캡쳐될 변수가 클로저에서 사용되는 방식에 따라 선택한다.

이것은 이동이 가능하다면, 어떤 타입으로 대여하는 것도 가능해야 하기 때문이다. 주의할 점은 역의 경우는 참이 아니다. 만약 매개변수가 Fn으로 주해되었다면 캡쳐되는 변수로 &mut T 혹은 T는 허용되지 않는다.

다음에 예제에서, Fn, FnMut, 그리고 FnOnce간에 사용 방식을 바꾸는 시도가 어떤 결과를 발생시키는지 확인해보자:

// .
fn apply<F>(f: F) where
// .
F: FnOnce() {
// ^ TODO: `Fn` `FnMut` .
f()
}
// `i32`
fn apply_to_3<F>(f: F) -> i32 where
// `i32` `i32` .
F: Fn(i32) -> i32 {
f(3)
}
fn main() {
use std::mem;
let greeting = "hello";
// - .
let mut farewell = "goodbye".to_owned();
// 2 : `greeting` `farewell` .
let diary = || {
// `greeting` `Fn` .
println!("I said {}.", greeting);
// `farewell` .
// `FnMut` .
farewell.push_str("!!!");
println!("Then I screamed {}.", farewell);
println!("Now I can sleep. zzzzz");
// drop `farewell` .
// `FnOnce` .
mem::drop(farewell);
};
// .
apply(diary);
// `double` `apply_to_3` trait .
let double = |x| 2 * x;
println!("3 doubled: {}", apply_to_3(double));
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

See also:

std::mem::drop, Fn, FnMut, and FnOnce

results matching ""

    No results matching ""