멀티패러다임 프로그래밍
멀티페러다임에 현대언어를 확장하는 방법
요즘에는 다양한페러다임을 하나에 언어에서 성숙하게 사용헐 수 있게 되었다.
특정 패러다임이 어울리는 부분에 적용하면 억지스럽지 않고 자연스러운 프로그래밍을 효율적으로 실현할 수 있다.
1.1 반복자패턴과 일급함수
이터러블은 객체지향의 gof 반복자 패턴에서 시작외었으며, 여러 언어에서 기본 빌트인으로 제공하면서 일급함수라는 개념과 만나 함수형으로 프로그래밍 할 수 있는 형태로 진화하였다.
ArrayLikeIterator 는 유사 배열을 어터러블로 바꿔준다
이터러블 특성을 이용하면 리스트 자료구조에 대한 지연평가 용이해진다.
이터러블의 지연성을 이용한 reverse
function reverse<T>(iterable: Iterable<T>): Iterable<T> {
return {
[Symbol.iterator]() {
const buffer: T[] = [];
for (const item of iterable) {
buffer.push(item);
}
let index = buffer.length - 1;
return {
next(): IteratorResult<T> {
if (index < 0) {
return { done: true, value: undefined as any };
}
return {
done: false,
value: buffer[index--],
};
},
};
},
};
}
비슷한 방법으로 map 이터러블 함수도 만들수 있고, 조합해서 사용할 경우에도 잘 동작한다.
map(str => str.tolowercase(), reverse(list))
성능이 중요한 코드일때 매우 유용하다.
- yield * 사용법
function* gen() {
yield* [1, 2, 3];
}
사실상 아래와 같은 의미
for (const value of [1, 2, 3]) {
yield value;
}
array, set, map 것들은 내장 이터러블 객체다.
map.entries 도 이터러블을 반환합니다.
제너레이터로 만든 객체는 이터러블 심볼 함수를 직접 구현 안해줘도 그 자체로 이터러블 객체가 된다.
꼬리호출 최적화는 재귀가 리턴하는 함수가 자기 자신을 호출하여 리턴하는 형태인데 … 이러면 콜스택이 하나 더 생성되지 않고 절약된다(stack overflow 위험이 없어진다). 하지만 js 구현체에서는 이런 부분을 엔젠에서 잘 구현하고 있지 않아서 큰 의미는 없다. 하지만 꼬리호출 최적화로 구현되면 코드 자체가 구조적으로 좋아지는 효과는 있다.
맵이나 셋 등 순회 가능한 요소들을 배열 상속으로 구현하지 않은것은 각 자료구조의 성격이 틀려서 그렇다.
불필요한 구조가 발생하면 복잡해지고 최적화가 어렵기 때문에 이터러블 인터페이스 프로토콜을 이용해 구현하도록 한것이다.
상속과 인터페이스는 틀린 개념이며 상속을 이용하면 코드간 결합도가 커져서 문제가 생길 가능성이 높아진다. 뭐가 더 우월하기 보다는 용도가 틀리다.
상황에 따라 적절히 사용하는게 좋다. 반복자패턴과 일급함수는 멀티페러다임 언어에서 함수형 코드를 구현하는 중요한 시발점을 제공한다.
함수형 프로그래밍과 타입시스템 그리고 LISP
const는 값이 바뀔수 없음을 의미하므로 리터럴로 평가된다.
고차함수가 반환하는 값을 추론할때 타입스크립트는 더 넓은 의미 값으로 추론하는 경향이 있다. 알아두면 좋다. (점점 포괄적인 타입으로 변화하다가 결국 어느시점에서는 unknown 으로 넓어짐)
이터러블 헬퍼함수 정의방법 타입설명과, 예제와 함께 자세히 설명됨.
메서드체이닝 함수형 객체를 만드는 기법 소개
LISP는 프로그램을 대이터로 데이터를 값으로 나타낼수 있는 함수형 언어고 클로저가 대표적인 리스프 언어다.
리스프는 last-value 향식을 따른다. 저자는 함수형 함수조합에 유리한 형태인 last-value를 설명하려고 하고있음.
리스프언어를 통해 함수형의 점진적 지연평가 특징 설명.
이터러블 프로토콜로 인해 지연평가가 용이한 구조에 대해 설명.
리스프는 매크로라는 기능으로 dsl을 쉽게 사용자가 만들 수 있다.
클로저는 파이프라인을 매크로로 ->>로 표현한다.
코드:객체:함수
주된 내용은 여러 함수형 언어로부터의 장점을 배워보고 자바스크립트 세계관으로 구현하는 예제가 책에 설명되어 있음
하스켈은 특히 언어 차원에서 커링을 지원함.
하스켈에서 “.” 은 합수합성, “$” 는 즉시실행 파이프 “&” 는 즉시실행(우->좌).
이터러블 객체는 지연 평가라는 특성 때문에 함수형 프로그래밍과 잘 맞는다. 둘 다 계산을 선언적으로 정의하고, 실제 값의 평가는 나중에 이루어진다.
함수형 패러다임은 코드가 곧 대이터고 데이터가 곧 로직인 메타플로그래밍이 가능하다.
비동기 프로그래밍
이 섹션에는 Promise 기본 사용법과, api 사용 예제가 자세히 설명되어 있음.
복잡한 케이스의 프로미스 사용 예와, 그걸 다시 함수형 파이프로 리팩토링하는 예제 구현되어 있음.
그냥 예제일 뿐이라서 금방 잊혀지는 내용임… 대충 구현의 요지를 읽고 넘어감.
AsynIterator -> 프로미스 감싸여진 next가 구현된 객체.
AsyncIterable -> Symbol.asyncItorator 를 키로 같고 AsynIterator를 리턴하는 함수를 구현한 객체
AsyncGenerator는 async function* 호출 결과로 생성되는 객체 타입이며, 그 객체가 AsyncIterable과 AsyncIterator를 동시에 구현한다.
실전 함수형 프로그래밍
약간… 책 분량을 채우기 위해 약간 어거지로 패턴을 만들어서 넣어둔 느낌?.
(어차피 이런 패턴을 외워서 사용하는 사람은 없음)
(그래도 그냥 참고로 대충 읽어둠)
1. 변형 누적 패턴
map and reduce
2. 중첩 변형 패턴
map을 연달아 사용
3. 반복자 효과 패턴
forEach로 순회하면서 부작용 일으킴.
반환값이 없는 메서드이기 때문에 부수효과를 암시하여 코드인지에 좋음
4. 필터 중단 패턴
filter 후 take 하면 지연효과로 효울적으로 순회개수를 제한함.
5. 무한 중단 패턴
필터중단이랑 비슷하누개념인데 이터러블 데이터에 take나 find를 걸면 모든 배열을 순회 안하고도 대이터를 사용헐수 있음
6. 분할 평탄 패턴
Chunk로 븐할후 그리고 분하을된 데이터 묶음을 처리 후 다시 평탄화.
데이터 갯수 제약이 있는 쿼리 같은 곳에 편리함.
7. 변형 평탄 패턴
map으로 변형후 다시 평탄…
8. 결합 누적 패턴
zip 으로 결합 후 reduce
9. 해시 매치 패턴
특정 키로 해시맵을 만들어 활용
책에 뒷부분은 거의 작가가 생각하는 형태의 함수형 패러다임을 사용하는 예제임으로 크게 리뷰에 남길것 없어보임