13장. 함수형 프로그래밍
Rust는 함수형 프로그래밍 패러다임을 지원하는 여러 기능을 제공합니다. \
함수형 프로그래밍은 순수 함수, 고차 함수, 클로저, 이터레이터 등을 사용하여 코드를 작성하는 스타일입니다.
순수 함수
순수 함수는 부작용이 없고, 동일한 입력에 대해 항상 동일한 출력을 반환하는 함수입니다.
순수 함수 예제
fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let result = add(2, 3);
println!("2 + 3 = {}", result);
}
위 예제에서 add 함수는 순수 함수입니다. 입력 값 a와 b에 대해 항상 동일한 결과를 반환합니다.
고차 함수
고차 함수는 다른 함수를 인자로 받거나, 함수를 반환하는 함수입니다.
고차 함수 예제
fn apply<F>(f: F, a: i32, b: i32) -> i32
where
F: Fn(i32, i32) -> i32,
{
f(a, b)
}
fn main() {
let sum = |a, b| a + b;
let product = |a, b| a * b;
println!("Sum: {}", apply(sum, 2, 3));
println!("Product: {}", apply(product, 2, 3));
}
위 예제에서 apply 함수는 고차 함수입니다. F 타입의 함수를 인자로 받아서 a와 b를 적용합니다. sum과 product 클로저를 사용하여 apply 함수를 호출합니다.
클로저
클로저는 주변 환경의 변수를 캡처할 수 있는 익명 함수입니다.
클로저 예제
fn main() {
let x = 10;
let add_x = |a: i32| a + x;
println!("Result: {}", add_x(5));
}
위 예제에서 add_x 클로저는 x 변수를 캡처하여 사용합니다. 클로저는 x의 값을 기억하고, a에 x를 더한 값을 반환합니다.
이터레이터
이터레이터는 컬렉션의 요소를 순회하는 객체입니다. Rust의 이터레이터는 함수형 프로그래밍 스타일로 데이터를 처리할 수 있는 다양한 메서드를 제공합니다.
이터레이터 예제
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
println!("Doubled: {:?}", doubled);
let sum: i32 = numbers.iter().sum();
println!("Sum: {}", sum);
let even_numbers: Vec<i32> = numbers.iter().filter(|&&x| x % 2 == 0).cloned().collect();
println!("Even numbers: {:?}", even_numbers);
}
위 예제에서 numbers 벡터의 이터레이터를 사용하여 각 요소를 두 배로 만들고, 합계를 구하고, 짝수만 필터링합니다. map, sum, filter 메서드를 사용하여 함수형 프로그래밍 스타일로 데이터를 처리합니다.
함수형 프로그래밍 요약
- 클로저
- 클로저 생성
- 기본 문법: |x| x + 1
- 단순 클로저: let add = |x, y| x + y; println!("1 + 2 = {}", add(1, 2));
- 다중 라인: let multiply = |x, y| { let result = x * y; result };
- 타입 명시: let divide = |x: f64, y: f64| -> f64 { x / y };
- move 클로저: let v = vec![1,2,3]; let print = move || println!("벡터: {:?}", v);
- 타입 추론과 명시
- 자동 타입 추론: let is_even = |x| x % 2 == 0;
- 제네릭 클로저: let first = |x: Vec| -> Option { x.into_iter().next() };
- FnOnce 트레잇: let consume = |v: Vec| { println!("소비: {:?}", v) };
- FnMut 트레잇: let mut sum = 0; let mut add = |x| { sum += x; sum };
- 환경 캡처
- 불변 참조: let factor = 2; let multiply = |x| x * factor;
- 가변 참조: let mut counter = 0; let mut count = || { counter += 1; counter };
- 소유권 이전: let data = String::from("hello"); let print = move || println!("{}", data);
- 반복자
- Iterator 트레잇
- next() 메서드: let mut iter = vec![1,2,3].iter(); assert_eq!(iter.next(), Some(&1));
- into_iter(): let v = vec![String::from("hello")]; for s in v.into_iter() { println!("{}", s); }
- itermut(): let mut v = vec![1,2,3]; for x in v.iter_mut() { _x = 2; }
- 반복자 어댑터
- map: let squares: Vec<_> = (0..5).map(|x| x * x).collect();
- filter: let evens: Vec<_> = (0..10).filter(|x| x % 2 == 0).collect();
- enumerate: for (i, v) in vec!['a', 'b', 'c'].iter().enumerate() { println!("{}번째: {}", i, v); }
- zip: let v1 = vec![1,2,3]; let v2 = vec![4,5,6];
let pairs: Vec<_> = v1.iter().zip(v2.iter()).collect();
- 소비자
- sum/product: let sum: i32 = (1..=5).sum(); let product: i32 = (1..=5).product();
- max/min: let numbers = vec![1,5,3,2,4]; let max = numbers.iter().max();
- fold/reduce: let sum = vec![1,2,3,4,5].iter().fold(0, |acc, &x| acc + x);
- any/all: let has_even = vec![1,2,3].iter().any(|&x| x % 2 == 0);
- find/position: let found = vec![1,2,3].iter().find(|&&x| x > 2);
참조: https://doc.rust-lang.org/book/ch13-00-functional-features.html