Search
🏛️

[FP & JS ES6+] 3. 지연성

Created
2023/01/22 13:11
Tags
Javascript
Functional Programming
Study
Last edited time
2023/10/05 14:06
Status
Done
Search
[FP & JS ES6+] 6. 비동기: 동시성 프로그래밍 (3) - async/await, Q&A
Javascript
Functional Programming
Study
2023/10/06 14:19
[FP & JS ES6+] 6. 비동기: 동시성 프로그래밍 (3) - async/await, Q&A
Javascript
Functional Programming
Study
2023/10/06 14:19

1. 지연성 (1)

1.1. range & L.range

range
배열로 평가 → 이터레이터로 순회
L.range
미리 배열을 평가하지 않음. 하나씩 값을 꺼내서 순회할때마다 평가
const range = l => { let i = -1; let res = []; while (++i < l) { res.push(i); } return res }; const L = {} L.range = function* (l) { let i = -1; while (++i < l) { yield i; } };
JavaScript
복사
예시 코드
효율성 테스트 코드

1.2. take

함수의 값을 받아서 원하는 길이만큼 자르는 함수
L.range를 활용하면 훨씬 효율성 증대 가능
const take = (l, iter) => { let res = []; for (const a of iter) { res.push(a); if (res.length === l) return res; } return res; };
JavaScript
복사
예시 코드

1.3. 지연 평가 (Lazy Evaluation)

이터러블 중심 프로그래밍에서의 지연 평가
제때 계산법
느긋한 계산법
제너레이터/이터레이터 프로토콜을 기반으로 구현
L.map
평가를 미루는 성질을 가지고 ,평가 순서를 달리 조작 할 수있는 준비가 되어 있는 이터레이터를 반환하는 제너레이터 함수
const L = {} L.map = function* (f, iter) { for (const a of iter) yield f(a); } // 예시 코드 const it = L.map(a => a + 10, [1, 2, 3]); log([...it]); log(it.next()); log(it.next()); log(it.next()); log(it.next());
JavaScript
복사
L.filter
const L = {} L.filter = function* (f, iter) { for (const a of iter) if (f(a)) yield a; } // 예시 코드 const it = L.filter(a => a % 2, [1, 2, 3, 4]); log([...it]);
JavaScript
복사

1.4. 즉시 평가 & 지연평가 비교

즉시평가 (range, map, filter)
평가순서는 순차적으로 진행
배열등을 즉시 평가하므로 성능이 지연평가에 비해 낮음
지연평가 (L.range, L.map, L.filter)
generator / iterator 활용 방식
iter.next() 는 앞 함수에서 만든 iterator가 실행해야하므로 역으로 평가가 진행됨
평가 순서는 역으로 진행
예시
/** * 즉시 평가 * range에서 값을 모두 만들어놓고 순차적으로 평가 진행 * * 평가 순서 * 1. range: [0, 1, 2, 3, ...] * 2. map: [10, 11, 12, 13, ...] * 3. filter: [11, 13, ...] * 4. take: [11, 13] */ go(range(10), map(n => n + 10), filter(n => n % 2), take(2), log); /** * 지연 평가 * 1. take(take할 걸 줘) -> filter(filter할 걸 줘) -> map (map 할걸 줘) -> range (0을 줄게) * 2. 0 값을 바탕으로 map -> filter -> take... (반복) * * 평가 순서 * 1. 0(range 첫번째 값) -> 10 (map) -> false (filter fail) * 2. 1(range) -> 11(map) -> true(filter) -> take */ go(L.range(10), L.map(n => n + 10), L.filter(n => n % 2), take(2), log);
JavaScript
복사
예시 코드 (전체)

1.5. map, filter 계열 함수의 결합 법칙

사용하는 데이터가 무엇이든지
사용하는 보조함수가 순수함수라면 무엇이든지
아래와 같이 결합한다면 둘다 결과가 같음
[[mapping, mapping], [filtering, filtering], [mapping, mapping]] = [[mapping, filtering, mapping], [mapping, filtering, mapping]]
JavaScript
복사
take 함수등을 통해 즉시평가/지연평가 구분없이 같은 결과를 낼 수 있는 것도 같은 맥락

2. 지연성 (2)

2.1. 결과를 만드는 함수 - reduce, take

지연성을 가지고 결과를 만들며, map, filter 등과 활용성이 높음
reduce
예시 코드
예시 코드 2
take & find
예시 코드
L.map & L.filter + take로 map, filter 만들기
예시 코드

2.2. flatten

L.flatten & flatten
yield *iterable  == for (const val of iterable) yield val;
예시 코드

2.3. flatMap

flatMap
flatten + map
L.flatMap
flatten + map 즉시 평가를 통해 생기는 비효율성 제거
지연성
예시 코드