일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 커링
- 해시
- 전화번호 목록
- 스프링 스케쥴러
- 루씬 인 액션
- @EnableScheduling
- 가장 큰 수
- @Getter
- 고차원 함수
- 프로그래머스
- K번째수
- @configuration
- 쿠버네티스
- Java
- 스택/큐
- 코딩 테스트
- 모던 자바 인 액션
- 영속 자료구조
- 검색 기능 확장
- 다리를 지나는 트럭
- 정렬
- @Setter
- 기능개발
- H-index
- 크론 표현식
- 롬복 어노테이션
- 완주하지 못한 선수
- @Data
- 알고리즘
- kubenetes
- Today
- Total
Today I Learned
[모던 자바 인 액션] 19장. 함수형 프로그래밍 기법 (1) 본문
이 장의 내용
- 일급 시민, 고차원 함수, 커링, 부분 적용
- 영속 자료구조
- 자바 스트림을 일반화하는 게으른 평가와 게으른 리스트
- 패턴 매칭, 자바에서 패턴 매칭을 흉내 내는 방법
- 참조 투명성과 캐싱
19.1 함수는 모든 곳에 존재한다
자바8에서는 ::연산자로 메서드 참조를 만들거나 람다 표현식으로 직접 함수값을 표현해서 메서드를 함수값으로 사용할 수 있다.
19.1.1 고차원 함수
Comparator.comparing처럼 다음 중 하나 이상의 동작을 수행하는 함수를 고차원 함수라 부른다.
- 하나 이상의 함수를 인수로 받음
- 함수를 결과로 반환
스트림 연산과 마찬가지로 고차원 함수를 구현 시, 인수로 전달된 함수가 부작용을 포함할 가능성을 염두에 두어야 한다.
19.1.2 커링
커링은 x와 y라는 두 인수를 받는 함수 f를 한 개의 인수를 받는 g라는 함수로 대체하는 기법이다.
static double converter(double x, double f, double b) {
return x * f + b;
}
...
double gbp = converter(1000, 0.6, 0);
//커링을 활용한 팩토리로 정의
static DoubleUnaryOperator curriedConvergter(double f, double b) {
return (double x) -> x * f + b;
}
...
DoubleUnaryOperator convertUSDtoGBP = curriedConvergter(0.6, 0);
double gbp = convertUSDtoGBP.applyAsDouble(1000);
첫 번째 함수는 인수 x, f, b를 항상 입력해줘야 한다.
두 번째 함수는 f, b 두 가지 인수만 함수에 요청하고, 반환된 함수에 인수 x를 이용해서 결과를 얻을 수 있다.
19.2 영속 자료구조
함수형 메서드에서는 전역 자료구조나 인수로 전달된 구조를 갱신할 수 없다.
자료 구조를 바꾼다면 같은 메서드를 두 번 호출했을 때 결과가 달라지면서 참조 투명성에 위배되고 인수를 결과로 단순하게 매핑할 수 있는 능력이 상실되기 때문이다.
19.2.1 파괴적인 갱신과 함수형
class TrainJourney {
public int price;
public TrainJourney onward; //이어지는 여정
...
}
static TrainJourney link(TrainJourney a, TrainJourney b) {
if (a == nul) return b;
TrainJourney t= a;
while(t.onward != null) {
t = t.onward;
}
t.onward =b;
return a;
}
위의 함수가 수행되면 a의 값까지 갱신시켜버린다. 기존에 a를 참조하던 영역에서 문제가 생길 수 있다.
static TrainJourney append(TrainJourney a, TrainJourney b) {
retun a == null ? b : new TrainJourney(a.price, append(a.onward, b));
}
위 코드는 기존 자료구조를 변경하지 않는다. 하지만 기존 a와 b가 바뀐다면 함께 갱신되므로 주의해야 한다.
19.2.2 트리를 사용한 다른 예제
다음은 HashMap같은 인터페이스를 구현하는 이진 트리 탐색 트리 중 update 메서드이다.
//Tree(key, val, left, right);
public static Tree update(String key, int newval, Tree t) {
if (t == null)
t = new Tree(key, newval, null, null);
else if (key.equal(t.key))
t.val = newval;
else if (key.compareTo(t.key) < 0)
t.left = update(key, newval, t.left);
else
t.right = update(key, newval, t.right);
return t;
}
두 가지 update 버전 모두 기존 트리를 변경하고 트리에 저장된 맵의 모든 사용자가 변경에 영향을 받는다.
19.2.3 함수형 접근법 사용
public static Tree fupdate(String key, int newval, Tree t) {
if (t == null) ?
new Tree(key, newval, null, null) :
k.equals(t.key) ?
new Tree(key, newval, t.left, t.right) :
k.compareTo(t.key) < 0 ?
new Tree(t.key, t.val, fupdate(key, newval, t.left), t.right) :
new Tree(t.key, t.val, t.left, fupdate(key, newval, t.right));
}
부작용 없는 하나의 표현식임을 강조하기 위해 하나의 조건문을 사용했지만, if-then-else 문으로 코드를 구현할 수도 있다.
fupdate를 호출하면 기존의 트리를 갱신하는 것이 아니라 새로운 노드를 만든다. 따라서 기존 자료구조에는 영향을 미치지 않는다.
'JAVA & Spring > 모던 자바 인 액션' 카테고리의 다른 글
[모던 자바 인 액션] 19장. 함수형 프로그래밍 기법 (2) (0) | 2021.12.13 |
---|---|
[모던 자바 인 액션] 18장. 함수형 관점으로 생각하기 (0) | 2021.11.30 |
[모던 자바 인 액션] 17장. 리액티브 프로그래밍 (0) | 2021.11.18 |
[모던 자바 인 액션] 16장. CompletableFuture : 안정적인 비동기 프로그래밍 (2) (0) | 2021.11.03 |
[모던 자바 인 액션] 16장. CompletableFuture : 안정적인 비동기 프로그래밍 (1) (0) | 2021.10.27 |