함수형
프로그래밍 언어가 추상 함수를 생성하고 조합함으로써 논리 연산을 표현할 수 있을 때 함수형 언어로 간주
람다
- 익명 함수를 지칭하는 용어
- 수학에서 사용하는 함수를 보다 단순하게 표현하는 방법
익명 함수
- 공통으로 일급 객체라는 특징을 가지고 있다.
- 일급 객체?
- 다른 객체들에 적용 가능한 연산을 모두 지원하는 개체
- 함수를 값으로 사용할 수도, 인자로 전달 및 변수로 사용하는 등의 연산들 가능하다.
람다 대수
- 추상화
- 단일 입력을 받는 익명 함수, 즉 람다
- 응용
- 값에 추상화가 적용되어 결과를 생성
- 개발자의 관점에서는 함수나 메서드 호출을 의미
- 베타 축약
- 추상된 변수를 적요된 인수로 대체
- 수학적 함수 선언식을 의미
연산의 놀리를 선언적 문장으로 표현할 수 있어야 하며, 표현식을 사용하여 결과와 프로그램이 작동하는 방식을 설명한다.
함수형 프로그램밍은 무엇을 해야 하는 지가 아닌 무엇을 원하는지를 표현한다.
표현식과 문장
- 표현식은 연산자, 피연산자, 메서드 호출로 구성되어 연산을 정의하고
리턴값을 계산
- 문장은 코드가 수행하는 동작을 기술한 독립적인 실행 단위를 말하여
리턴값이 없는
메서드 호출을 포함 - 표현식과 문장의 차이는 값의 반환 유무이다.
함수형 개념
'어떻게 해결할 것인가'를 고민하는 명령형 프로그래밍과는 반대로, '무엇을 해결할 것인가'에 초점을 맞춘다.
순수 함수
순수 함수
- 동일한 입력에 대해 항상 동일한 출력을 반환해야 한다.
- 어떠한 Side Effect 없이 자기 충족적 성질을 가진다.
외부 코드에 의존하지 않는 순수함수는public String toLowercase(String str) { return str; }
참조 투명성
을 가진다
참조 투명성
- 외부 코드에 의존하지 않는다.
- Side Effect 없이 관련 값을 대체할 수 있다면 참조상 투명하다.
위의 두가지 조건 중 하나라도 위반하면 불순 함수로 간주된다.
불순함수
public String buildGreeting(String name) {
var now = LocalTime.now();
if (now.getHour() < 12) {
return "Good morning " + name;
} else {
return "Hello " + name;
}
}
- 리턴값이 현재 시간을 나타내는 LocalTime에 의존하고 있으며
- 동일한 입력을 해도 시간에 따라 다른 결과값을 반환한다.
일급 함수 & 고차 함수
일급 함수
- 함수 자체를 다른 함수에
인수로 전달하거나, 반환값으로 사용
- 변수에 할당할 수 있는 함수를 지칭한다.
- 함수를 객체와 동일하게 사용할 수 있다는 의미
- 함수라는 대상이 값으로서 사용될 수 있다.
고차 함수
- 일급 함수의 특성을 바탕으로 함수를
인수로 받거나 반환
한다.
커링 함수
여러 개의 인수를 받는 함수들을 분리하여 인수를 하나씩만 받는 함수의 체인으로 변환, 즉 함수를 반환하는 함수이다.
const curry = fn => fn2 => a => b => fn(a,b) + fn2(a,b);
const add = (a,b) => a + b;
const multiply = (a,b) => a * b;
curry(add)(multiply)(3)(5);
public static void main(String[] args) {
int result1 = add(2, 3);
System.out.println(result1);
IntUnaryOperator addTwo = curriedAdd(2).apply(3);
int result2 = addTwo.applyAsInt(4);
System.out.println(result2);
}
static int add(int x, int y) {
return x + y;
}
static IntFunction<IntUnaryOperator> curriedAdd(int x) {
return y -> z -> x + y + z;
}
함수형 장단점
장점
1. 간결성
- 가변 상태이며 Side Effect가 없는 경우, 해야할 일만 수행하므로 함수는 간결해진다.
2. 일관성
- 순수함수와 불변성이 함께 사용됐을 때, 코드의 예측 가능성이 높아지고 동기화 문제나 상태 변경과 같은 문제를 초래하지 않아 일관성이 보장된다.
3. 정확성
- 일관성을 갖춘 코드는 정확한 코드를 만든다.
- 코드가 순수할수록 논리적 추론이 쉬워지므로 디버깅과 테스트에 용이하다.
4. 안전한 동시성
- 순수함수와 불변성으로 인해 병렬 및 동시성 작업이 더욱 쉬워진다.
5. 모듈성
- 독립적인 함수(순수함수, 고차함수, 커링함수 등)는 재사용성과 모듈성을 제공한다.
6. 테스트 용이성
- 순수 함수, 참조 투명성, 불변성, 역할 분리와 같은 함수형 개념은 테스트와 검증을 더욱 쉽게 만든다.
단점
1. 러닝 커브
- 수학 용어와 개념을 기반으로 하기 때문에 어렵게 느껴질 수 있다.
2. 고수준 추상화
- OOP는 객체를 사용하여 추상화를 모델링하는 반면, 함수형 프로그래밍은 더 높은 추상화 수준을 사용한다.
- 멋진 코드를 작성할 순 있지만 이해하기 어려울 수 있다.
3. 상태 처리
- OOP에서는 setter를 사용하여 상태를 변경할 수 있다.
- 함수형 프로그래밍의 불변성 접근 방식은 버그 가능성을 제거하지만,
- 자료 구조를 실제로 변경해야 하는 경우 상태를 변경하는 것이 어려울 수 있다.
4. 성능 영향도
- 불변성이나 재귀와 같은 함수형 기술은 오버헤드로 인해 성능이 저하될 수 있다.
5. 최적화 문제 상황
함수형 개념과 실제 적용 사이에는 타협이 필요하다.
하지만 함수형 개념의 장점은 단점을 능가하거나 어떠한 형태로든 완화할 수 있다.
'함수형 프로그래밍' 카테고리의 다른 글
[ch.06] 스트림을 이용한 데이터 처리 (0) | 2024.06.06 |
---|---|
[ch.05] 레코드 (0) | 2024.06.01 |
[ch.04] 가변성 & 불변성 (0) | 2024.05.23 |
[ch.03] JDK 함수형 인터페이스 (0) | 2024.05.16 |
[ch.02] 함수형 자바 (0) | 2024.05.09 |