람다와 클로저
C#과 Rust는 함수를 일급 값으로 다루며 _고차 함수_를 작성할 수 있습니다.
고차 함수는 다른 함수를 인수로 받아 호출자가 함수 동작의 일부를 제공하도록
합니다. C#에서는 타입 안전한 함수 참조를 대리자로 표현하며, Func와
Action을 자주 사용합니다. _람다 식_으로 대리자 인스턴스를 즉석에서
만들 수 있습니다.
Rust에도 함수 포인터가 있습니다. 가장 간단한 형태는 fn 타입입니다.
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
f(arg) + f(arg)
}
fn main() {
let answer = do_twice(|x| x + 1, 5);
println!("The answer is: {}", answer); // 출력: The answer is: 12
}
Rust는 _함수 포인터_와 _클로저_를 구분합니다. 함수 포인터의 타입은
fn으로 정의합니다. 클로저는 주변 어휘 범위의 변수를 참조할 수 있지만
함수 포인터는 그럴 수 없습니다. C#에도 delegate* 형태의
함수 포인터가 있습니다. 관리 코드에서 타입 안전하게
사용하는 정적 람다 식은 Rust의 함수 포인터와 더 가깝습니다.
클로저를 받는 함수와 메서드는 Fn, FnMut, FnOnce 트레이트 중 하나를
제약 조건으로 둔 제네릭 타입을 사용합니다. 함수 포인터나 클로저 값을
전달할 때는 앞 예제의 |x| x + 1 같은 _클로저 식_을 작성합니다.
C#의 람다 식과 역할이 같습니다. 클로저 식이 함수 포인터가 될지 클로저가
될지는 주변 변수를 참조하는지에 따라 달라집니다.
클로저가 주변 변수를 캡처하면 소유권 규칙도 적용됩니다. 캡처한 값의
소유권이 클로저로 이동할 수 있기 때문입니다. 자세한 내용은 The Rust
Programming Language의 클로저에서 캡처한 값 이동과 Fn 트레이트
절에서 확인할 수 있습니다.