함수형 프로그래밍과 JavaScript ES6+ 강의를 듣고 정리한 내용입니다.
✅ L.map + take로 map 만들기
const map = curry((f, iter) => {
let res = [];
iter = iter[Symbol.iterator]();
let cur;
while (!(cur = iter.next()).done) {
const a = cur.value;
res.push(f(a));
}
return res;
});
L.map = curry(function* (f, iter) {
iter = iter[Symbol.iterator]();
let cur;
while (!(cur = iter.next()).done) {
const a = cur.value;
yield f(a);
}
});
console.log(map(a => a + 10, L.range(4)));
// output
// [10, 11, 12, 13]
위의 코드는 기본적인 map과 L.map의 구현이다.
동작을 더 자세히 보기 위해 for of문 대신 이터레이터의 구현부터 while문을 사용하였다.
L.map은 지연 평가를 하도록 설계되어 있다.
L.map이 미뤄두었던 평가를 map처럼 하기 위해서는 일부분에 대해서가 아닌 인자로 들어오는 이터러블의 모든 요소에 대해 평가를 하도록 하면 된다.
const map = curry((f, iter) => go(
iter,
L.map(f),
take(Infinity)
));
console.log(map(a => a + 10, L.range(4)));
// output
// [10, 11, 12, 13]
take(Infinity)를 통해 iter에 대한 L.map의 모든 결과를 가져오도록 했다.
이 과정에서 go문의 첫 번째 요소로 iter를 넘기고 있고 이 iter는 그대로 L.map의 iter 자리에 들어가게 되므로 다음과 같이 중복성을 없앨 수 있다.
const map = curry((f, iter) => go(
L.map(f, iter),
take(Infinity)
));
그런데 또 map 함수의 인자로 f와 iter가 주어지고 이것이 L.map에 그대로 전해지기 때문에 이 중복성도 없애면 최종적으로 다음의 결과를 얻을 수 있다.
const map = curry(
pipe(
L.map,
take(Infinity)
)
);
✅ L.filter + take로 filter 만들기
const filter = curry((f, iter) => {
let res = [];
iter = iter[Symbol.iterator]();
let cur;
while (!(cur = iter.next()).done) {
const a = cur.value;
if (f(a)) res.push(a);
}
return res;
});
L.filter = curry(function* (f, iter) {
iter = iter[Symbol.iterator]();
let cur;
while (!(cur = iter.next()).done) {
const a = cur.value;
if (f(a)) yield a;
}
});
filter도 map과 같이 L.filter와 take를 이용해 구현할 수 있다.
const filter = curry(
pipe(
L.filter,
take(Infinity)
)
);
console.log(filter((a) => a % 2, range(10)));
// output
// [1, 3, 5, 7, 9]
'JavaScript' 카테고리의 다른 글
[FP&ES6+] L.flatMap, flatMap (0) | 2021.12.28 |
---|---|
[FP&ES6+] L.flatten, flatten (0) | 2021.12.27 |
[FP&ES6+] 결과를 만드는 함수 - take (0) | 2021.12.27 |
[FP&ES6+] 결과를 만드는 함수 - reduce (0) | 2021.12.27 |
[FP&ES6+] 즉시 평가와 지연 평가의 비교 (0) | 2021.12.25 |
댓글