프로그래밍
함수형 프로그래밍
강철곰탱이
2024. 1. 3. 01:27
1. 프로그래밍 패러다임
프로그래밍 패러다임(Programming Paradigm)은 프로그래머에게 프로그래밍의 관점을 갖게 해주는 역할을 하는 개발 방법론이다.
명령형 vs 선언형
🏷 명령형
- 컴퓨터에게 정확한 수행절차를 지시하는 방식
- 프로그램이 "어떻게(How)" 수행되어야 하는지 설명
🏷 선언형
- 어떻게 할지 명시하지 않고, 원하는 결과를 선언하는 방식
- 프로그램이 "무엇을(What)" 수행할지에 대해 설명
📝 예시
배달음식 주문하기
- 명령형(How): 배달 앱을 실행한다. 치킨을 골라서 장바구니에 담는다. 배달 받을 주소와 요청사항을 입력하고 치킨을 계산한다.
- 선언형(What): 치킨을 주문한다.
물론 선언적 방식의 접근을 위해 "어떻게 접근하는 가"가 먼저 추상화되어있어야 한다.
=> 선언적 접근 방식의 기저에는 명령형이 깔려있고 추상화된 것이다.
2. 함수형 프로그래밍
함수형 프로그래밍은 선언형 패러다임의 일종이다.
- 작은 문제를 해결하기 위해 모든 것을 순수 함수로 나누어 문제를 해결하는 기법
- "대입문이 없는 프로그래밍"
- 같은 input에 동일한 output이 나온다. => 순수 함수
- 예로 클로저, 하스켈, 리스프 등이 있다.
함수형 프로그래밍은 "순수 함수"들을 블록처럼 쌓아 로직을 구현하고 "고차 함수"를 통해 재사용성을 높인 프로그래밍 패러다임이다.
부수 효과(Side Effect)
: 함수가 실행되는 동안 그 외부에 영향을 미치는 모든 변화를 가리킨다.
- 프로그램이 실행되는 동안 전역 변수나 외부 변수를 변경하는 경우
- 예외를 발생시키거나 처리하는 동작
순수 함수(Pure Function)
- 동일한 입력에 대해 항상 동일한 출력을 반환
- Memory or I/O관점에서 side effect를 제거한 함수
func add(a: Int, b: Int) -> Int {
return a + b
}
이 함수는 매개변수 a, b에만 영향을 받으므로 항상 동일한 결과를 반환하므로 순수 함수이다.
고차 함수(Higher-Order Function)
- 함수를 다른 함수의 인자로 받거나, 함수를 반환하거나, 함수를 변수에 할당할 수 있는 함수
- 함수를 1급 객체로 취급한다.
- 예로 map, filter, reduce등이 있다.
let numbers = [1, 2, 3, 4, 5]
let result = numbers.map { $0 * $0 }
// result = [1, 4, 9, 16, 25]
map 함수는 배열의 각 요소에 함수를 적용하여 새로운 배열을 만드는 고차 함수이다.
1급 객체(First-Class Object)
- 변수나 메서드에 함수를 할당할 수 있다.
- 함수 안에 함수를 매개변수로 담을 수 있다.
- 함수가 함수를 반환할 수 있다.
참조 투명성(Referential Transparency)
- 동일한 입력에 대해 항상 동일한 출력을 반환
- side effect가 없을 때 해당 함수는 참조적으로 투명하다고 할 수 있다.
- 참조 투명성을 통해 기존의 값은 변경되지 않고 유지된다.(Immutable Data)
예를 들어, 다음 함수는 참조 투명하다고 할 수 있다.
func add(a: Int, b: Int) -> Int {
return a + b
}
반면에 참조 투명하지 않은 함수는 외부의 상태나 외부의 다른 변수에 의해 결과가 영향을 받는다.
아래의 코드는 num이라는 전역변수를 두고 함수가 호출될 때마다 num의 값이 변하니 참조 투명하지 않다고 할 수 있다.
var num = 5
func add(a: Int) -> Int {
num += a
return num
}
🟢 장점
- 불변성과 예측 가능성: 동일한 입력에 항상 동일한 출력을 반환하므로 예측 가능성이 높다.
- 병렬 프로그래밍 용이성: 상태 변경이 없고 side effect가 적은 함수들로 이루어져 있어 병렬 처리가 더 쉽고 안전하게 이루어질 수 있다.
- 테스트 용이성:각 함수가 독립적으로 동작하므로 테스트 간단하고 효과적으로 이루어진다.
- 재사용성 증가: 함수의 모듈성이 높아져 함수를 조합하여 큰 기능을 만들 수 있어 코드의 재사용성이 증가한다.
🔴 단점
- 유연성 부족: 불변성을 유지하기 때문에 변수의 값을 변경하거나 갱신하는 것이 제한된다.
참고