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

입력 파라미터로 사용

Rust는 대부분 타입 어노테이션 없이 즉석에서 변수를 캡처하는 방식을 선택하지만, 함수를 작성할 때는 이러한 모호함이 허용되지 않습니다. 클로저를 입력 파라미터로 받을 때, 클로저의 전체 타입은 몇 가지 트레이트 중 하나를 사용하여 어노테이션되어야 하며, 이는 클로저가 캡처된 값으로 무엇을 하는지에 따라 결정됩니다. 제약이 강한 순서대로 나열하면 다음과 같습니다:

  • Fn: 클로저가 캡처된 값을 참조(&T)로 사용합니다
  • FnMut: 클로저가 캡처된 값을 가변 참조(&mut T)로 사용합니다
  • FnOnce: 클로저가 캡처된 값을 값(T)으로 사용합니다

변수별로 컴파일러는 가능한 가장 제약이 적은 방식으로 변수를 캡처합니다.

예를 들어, FnOnce로 어노테이션된 파라미터를 생각해 보세요. 이는 클로저가 &T, &mut T, 또는 T로 캡처할 수 있음을 나타내지만, 컴파일러는 최종적으로 클로저 내에서 캡처된 변수가 어떻게 사용되는지에 따라 선택합니다.

이동(move)이 가능하다면 어떤 유형의 빌림(borrow)도 가능해야 하기 때문입니다. 그 반대는 성립하지 않음에 유의하세요. 파라미터가 Fn으로 어노테이션된 경우, &mut TT로 변수를 캡처하는 것은 허용되지 않습니다. 하지만 &T는 허용됩니다.

다음 예제에서 Fn, FnMut, FnOnce의 사용을 서로 바꿔보며 어떤 일이 일어나는지 확인해 보세요:

// 클로저를 인자로 받아 호출하는 함수입니다.
// <F>는 F가 "제네릭 타입 파라미터"임을 나타냅니다.
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 = "안녕";
    // 복사되지 않는 타입.
// `to_owned`는 빌려온 데이터로부터 소유권이 있는 데이터를 생성합니다.
    let mut farewell = "잘 가요".to_owned();

    // 두 개의 변수를 캡처합니다: `greeting`은 참조로, `farewell`은 값으로.
    let diary = || {
        // `greeting`은 참조에 의한 방식입니다: `Fn`이 필요합니다.
        println!("저는 {}라고 말했습니다.", greeting);

        // 수정을 위해 `farewell`을 가변 참조로 캡처해야 합니다.
// 이제 `FnMut`가 필요합니다.
        farewell.push_str("!!!");
        println!("그러고 나서 저는 {}라고 소리쳤습니다.", farewell);
        println!("이제 잘 수 있겠네요. zzzzz");

        // 수동으로 drop을 호출하면 `farewell`을 값으로
// 캡처해야 합니다. 이제 `FnOnce`가 필요합니다.
        mem::drop(farewell);
    };

    // 클로저를 적용하는 함수를 호출합니다.
    apply(diary);

    // `double`은 `apply_to_3`의 트레이트 바운드를 만족합니다
    let double = |x| 2 * x;

    println!("3의 두 배: {}", apply_to_3(double));
}

참고:

std::mem::drop, Fn, FnMut, 제네릭, whereFnOnce