클로저와 반복자: 현대적 프로그래밍의 도구
학습 목표: 파이썬의
lambda와 제너레이터가 Rust에서 어떻게 대응되는지 배웁니다. 더 강력한 **클로저(Closure)**와 지연 연산을 수행하는 반복자(Iterator) 체인을 익히고, 코드 생성을 돕는 매크로(Macro) 시스템의 기초를 파악합니다.
1. 클로저: 파이썬의 람다 그 이상
파이썬의 lambda는 한 줄짜리 표현식만 가능하지만, Rust의 클로저는 여러 줄의 로직을 가질 수 있으며 주변 환경의 변수를 캡처하는 방식도 훨씬 정교합니다.
# [Python] 람다
double = lambda x: x * 2
#![allow(unused)] fn main() { // [Rust] 클로저 (|인자| 바디) let double = |x: i32| x * 2; let result = double(5); // 10 // 여러 줄 클로저 let complex = |x| { let y = x + 1; y * 2 }; }
💡 실무 팁: move 키워드
클로저 내부에서 외부 변수의 소유권을 가져와야 할 때(예: 멀티스레드로 전달할 때) move 키워드를 사용합니다. 이는 파이썬의 늦은 바인딩(Late Binding) 문제를 원천적으로 방지합니다.
2. 반복자: 제너레이터와 컴프리헨션의 진화
파이썬의 리스트 컴프리헨션이나 제너레이터 표현식은 Rust에서 반복자 체인으로 표현됩니다.
| 용도 | Python (컴프리헨션) | Rust (반복자 체인) |
|---|---|---|
| 변환 | [x*2 for x in data] | .iter().map(|x| x * 2) |
| 필터링 | [x for x in data if x > 0] | .iter().filter(|&x| x > 0) |
| 인덱스 포함 | enumerate(data) | .iter().enumerate() |
| 결과 수집 | list(...) / set(...) | .collect::<Vec<_>>() / .collect::<HashSet<_>>() |
💡 지연 연산 (Lazy Evaluation)
Rust의 모든 반복자 체인은 .collect()나 반복문에서 실제로 사용되기 전까지는 아무런 동작도 하지 않습니다. 이는 메모리 효율을 극대화하며 복잡한 데이터 처리를 최적화합니다.
3. 매크로: 컴파일 타임의 마법
파이썬이 데코레이터나 메타클래스를 통해 런타임에 동적으로 기능을 추가한다면, Rust는 매크로를 통해 컴파일 타임에 코드를 생성합니다.
println!/format!: 가변 인자를 지원하는 출력 매크로.vec![...]: 벡터를 쉽게 생성하는 매크로.#[derive(...)]:Debug,Clone등 반복적인 트레이트 구현을 자동으로 생성해 주는 매크로 (파이썬의@dataclass와 유사).
💡 실무 팁: dbg! 매크로를 활용하세요
파이썬에서 디버깅할 때 print(f"{x=}")를 즐겨 쓰시나요? Rust에는 dbg!(x)가 있습니다. 파일 이름, 줄 번호와 함께 변수의 값을 시각적으로 예쁘게 출력해 주며, 값을 그대로 반환하므로 코드 중간에 끼워 넣기 매우 편리합니다.