[functional-js] C.reduce, C.take
이 글은 유인동님의 함수형 프로그래밍 강의내용을 정리한 글입니다.
지연된 함수열을 병렬적으로 평가하기 - C.reduce
const delay1000 = a =>
new Promise(resolve => setTimeout(() => resolve(a), 1000));
go(
[1, 2, 3, 4, 5, 6],
L.map(a => delay1000(a * a)),
L.filter(a => a % 2),
reduce(add),
console.log
);
L.map에서 한번 실행할때 마다 1초정도 걸리는데, 총 6개의 인자이므로 6초가 걸린다.
1개씩 실행시켜서 코드가 순회하기 때문이다.
이를 순차적이 아닌 병렬적으로 처리한다면 시간은 단축될 것이다.
병렬적으로 동작하는 C.reduce를 만들어 보자.
const C = {};
C.reduce = curry((f, acc, iter) =>
iter ? reduce(f, acc, [...iter]) : reduce(f, [...acc])
);
reduce로 해당하는 코드를 그대로 넘기지만, [...iter]
를 통해서 대기된 함수를 모두 다 실행을 시켜버리고 다시한번 reduce에서 값을 꺼낸다.
즉, go 첫 인자로 나온 값들을 실행을 전부 한 후 개별적으로 비동기 제어를 해서 앞에서부터 누적을 시키는 것이다.
// 순차적
console.time('');
go(
[1, 2, 3, 4, 5, 6],
L.map(a => delay1000(a * a)),
L.filter(a => a % 2),
reduce(add),
console.log, // 35
_ => console.timeEnd('')
);
// 약 6000ms
// 병렬적
console.time('');
go(
[1, 2, 3, 4, 5, 6],
L.map(a => delay1000(a * a)),
L.filter(a => a % 2),
C.reduce(add),
console.log, // 35
_ => console.timeEnd('')
);
// 약 1000ms
const C = {};
C.reduce = curry((f, acc, iter) =>
iter ? reduce(f, acc, [...iter]) : reduce(f, [...acc])
);
const delay1000 = a =>
new Promise(resolve => setTimeout(() => resolve(a), 1000));
go(
[1, 2, 3, 4, 5, 6],
L.map(a => delay1000(a * a)),
L.filter(a => delay1000(a % 2)),
L.map(a => delay1000(a * a)),
C.reduce(add),
console.log
);
catch되지 않은 부분이 있다고 나오지만, 결과는 정상적으로 나온다.
자바스크립트 특성상 콜스택에 프로미스 reject이 있으면 출력이 된다.
catch되지 않는 부분이 있지만, 이후에 잘 catch를 해서 정리를 해줄 것이기 때문에, 비동기적으로 해당하는 에러를 캐치해줄 것이란것을 명시해줘야 한다.
function noop() {}
const catchNoop = arr => (
arr.forEach(a => (a instanceof Promise ? a.catch(noop) : a)), arr
);
C.reduce = curry((f, acc, iter) => {
const iter2 = catchNoop(iter ? [...iter] : [...acc]);
return iter ? reduce(f, acc, iter2) : reduce(f, iter2);
});
위와 같이 해주면, 정상적으로 동작하면서, catch에러를 품지않는다.
C.take = curry((l, iter) => take(l, catchNoop([...iter])));
take도 똑같은 방식으로 작성할 수 있다.
go(
[1, 2, 3, 4, 5, 6],
L.map(a => delay1000(a * a)),
L.filter(a => delay1000(a % 2)),
L.map(a => delay1000(a * a)),
C.take(2),
reduce(add),
console.log
);
C.take도 병렬적으로 실행되기 때문에 기존 take보다 빠르게 실행된다.
Author And Source
이 문제에 관하여([functional-js] C.reduce, C.take), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@younoah/functional-js-C.reduce-C.take저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)