Rust에서 클로저(Closure)란 무엇인가요?
Rust에서 클로저(Closure)는 다른 언어의 람다(lambda) 또는 익명 함수에 해당합니다. 변수에 저장하거나 다른 함수의 인자로 전달할 수 있는 익명 함수로, 주변 환경의 변수들을 캡처할 수 있는 특징이 있습니다.
간단한 예제를 통해 클로저의 기본 문법을 알아보겠습니다.
fn main() {
let add = |x, y| x + y;
println!("3 + 5 = {}", add(3, 5));
}
위 예제에서 add
는 |x, y| x + y
라는 클로저를 저장한 변수입니다. 일반 함수처럼 사용할 수 있으며, 타입을 명시하지 않아도 컴파일러가 자동으로 추론해 줍니다.
클로저 vs 일반 함수: 무엇이 다를까요?
Rust에서는 클로저와 일반 함수 모두 함수를 정의할 수 있지만, 클로저는 다음과 같은 차이점을 가집니다:
- 익명 함수로서 변수에 저장하거나 다른 함수에 인자로 전달 가능
- 외부 변수 캡처 가능
- 타입 추론이 가능해 더 간결한 코드 작성 가능
fn main() {
let name = "Rust";
let say_hello = || println!("Hello, {}", name);
say_hello();
}
위 예제에서 클로저 say_hello
는 외부 변수 name
을 캡처하여 사용할 수 있습니다. 일반 함수에서는 이와 같은 동작이 불가능합니다.
클로저의 타입과 Fn, FnMut, FnOnce
Rust에서는 클로저의 동작 방식에 따라 세 가지 트레잇 중 하나를 자동으로 구현합니다:
Fn
: 클로저가 환경을 불변 참조로 캡처FnMut
: 가변 참조로 캡처FnOnce
: 환경을 이동(move)하여 소유
fn apply(f: F) {
f();
}
fn main() {
let message = "Hello";
apply(|| println!("{}", message));
}
이 예제는 Fn
트레잇을 사용하는 함수를 정의하고, 클로저를 인자로 전달합니다. 클로저의 타입은 자동 추론되며, 적절한 트레잇이 적용됩니다.
move 키워드로 소유권 이동
클로저에서 환경 변수를 소유권 이동으로 캡처하고자 할 때는 move
키워드를 사용합니다.
fn main() {
let name = String::from("Rust");
let say = move || println!("Welcome, {}", name);
say();
// name은 move로 인해 더 이상 사용할 수 없음
}
이 경우 say
클로저는 name
의 소유권을 가져가므로, 클로저 호출 이후 name
을 사용할 수 없습니다.
함수형 프로그래밍의 기초 개념
클로저는 Rust에서 함수형 프로그래밍 패러다임을 구현하는 데 핵심적인 역할을 합니다. 함수형 프로그래밍은 다음과 같은 특징을 지닙니다:
- 함수는 일급 객체로, 변수에 저장하거나 전달 가능
- 순수 함수(pure function)를 중시
- 불변성(immutability) 강조
- 고차 함수(higher-order function) 사용
고차 함수와 map, filter, fold 사용 예제
Rust의 Iterator
와 함께 사용하는 map
, filter
, fold
등은 대표적인 함수형 프로그래밍 요소입니다.
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let doubled: Vec<_> = numbers.iter().map(|x| x * 2).collect();
println!("Doubled: {:?}", doubled);
let even: Vec<_> = numbers.iter().filter(|&x| x % 2 == 0).collect();
println!("Even: {:?}", even);
let sum: i32 = numbers.iter().fold(0, |acc, x| acc + x);
println!("Sum: {}", sum);
}
이처럼 클로저를 활용한 고차 함수는 Rust에서 가독성 높고 선언적인 스타일의 코드 작성을 가능하게 해 줍니다.
결론: Rust 클로저는 함수형 프로그래밍의 시작점
Rust에서의 클로저는 간단한 람다 표현을 넘어서, 메모리 안전성과 강력한 타입 시스템을 기반으로 한 함수형 프로그래밍을 실현하는 중요한 도구입니다. 클로저를 사용하면 더 유연하고 재사용 가능한 코드를 작성할 수 있으며, map
, filter
, fold
같은 고차 함수와 함께 사용하면 Rust 코드의 표현력을 크게 향상시킬 수 있습니다.
Rust 초보자라면 다양한 클로저 예제를 실습하면서 개념을 체득하고, 함수형 프로그래밍 스타일을 익혀보세요. 실전 개발에서도 매우 유용하게 쓰일 수 있습니다.