reduce나 take는 최종적으로 어떤 함수의 결과를 만드는 함수라고 볼 수 있다.
map이나 filter 같은 함수는 배열이나 이터러블한 값 즉 모나딕한 값에 안쪽에 있는 원소들에게 함수들을 합성해 놓는 역할을 한다면
reduce나 take같은 함수들은 이터러블이나 배열같이 안쪽에 있는 값들을 꺼내서 더해버리거나 (a b c d e들어있으면 a와 b를 꺼내서 더해버린다거나 하는 식으로)
배열형태의 값이나 이터레이터 형태로 있는 값을 꺼내서 깨뜨려 버려야 하기 때문에 reduce같은 함수들은 실제로 최종적으로 결과를 만드는 함수라고 볼 수 있다.
결론
map filter같은 함수는 지연성을 가질 수 있다고 볼 수 있고 reduce같은 함수들은 실제로 연산을 시작하는(연산의 시작점을 알리는) 함수라고 볼 수 있다.
그래서 함수들을 만들 때 map filter를 반복하다가 특정지점에서 reduce같은 함수를 통해서 깨뜨려서 연산을 시키고 함수를 종료하거나 다음 로직을 만들어 가는 식으로 reduce같은 함수는 중간에 연산을 시작하는 역할을 한다고 볼 수 있다.
a로 부터 b라는 값을 만들려고 할 때 a를 받아서 map filter들을 반복하다가
어떠한 reduce로 최종적으로 값을 만들어서 return하겠다라고 사고하면서 프로그래밍을 해야한다.
take같은 함수도 값을 2개만 yield하기로 약속하는 식으로 지연성을 줄 수 있지만 실제로 몇 개로 떨어질지 모르는 배열에서 특정 개수의 배열로 축약을 하고 완성을 지어버리는 특성때문에 take 자체도 지연성을 가지는 거 보다는 take를 한 시점에 연산이 이루어지는 것이 프로그래밍 하는 부분에 있어서 좀 더 편리하다고 볼 수 있다.
즉, 변수에 여러군데 할당하거나 할 때 편리하다고 볼 수 있다
queryStr 함수 만들기
reduce를 사용해서 객체로 부터 url의 queryStr부분을 얻어내는 코드를 작성해보자.
함수 이름을 짓고(queryStr) 인자는 obj를 받고 받은 인자는 그대로 리턴하고, queryStr을 쓰면서 limit과 offset, type를 지정해준다. 그리고 queryStr로 변환해주는데,
const queryStr = obj => obj;
log(queryStr({ limit: 10, offset: 10, type: 'notice' }));
// {limit: 10, offset: 10, type: "notice"}
obj를 통해서 limit과 10 offset 10, type notice 값을 가지고 쿼리스트링을 만들어야 해서 key와 value를 모두 추출하는 작업을 해본다. go를 이용해서 Object.entries라는 함수를 사용해서 key value를 entries로 변환을 해준다.
<script>
const queryStr = obj => go(
obj,
Object.entries
);
log(queryStr({ limit: 10, offset: 10, type: 'notice' }));
</script>
map을 이용해 구조분해를 해서 key와 value를 받고 결과를 출력해보면 아래와 같다.
<script>
const queryStr = obj => go(
obj,
Object.entries,
map(([k, v]) => `${k}=${v}`)
);
log(queryStr({ limit: 10, offset: 10, type: 'notice' }));
</script>
그리고 reduce를 통해서 a와 b를 받아서 그 사이에 $줘서 결과를 출력해보면 아래와 같다.
<script>
const queryStr = obj => go(
obj,
Object.entries,
map(([k, v]) => `${k}=${v}`),
reduce((a, b) => `${a}&${b}`)
);
log(queryStr({ limit: 10, offset: 10, type: 'notice' }));
</script>
// limit=10&offset=10&type=notice
reduce를 이용해 a로 시작해서 완전히 b를 만들어 낼 때(queryStr을 만들어 낼 때) 함수적으로 Object.entries로 바꾼다음에 map형식으로 바꾼다음 마지막으로 reduce로 축약해서 결과를 완성짓는다라고 로직을 짤 수 있다.
obj를 받아서 그대로 obj를 전달하고 있기 때문에 아래와 같이 pipe를 이용해 변경될 수 있다.
<script>
const queryStr = pipe(
Object.entries,
map(([k, v]) => `${k}=${v}`),
reduce((a, b) => `${a}&${b}`)
);
log(queryStr({ limit: 10, offset: 10, type: 'notice' }));
</script>
<출처 : 유인동 함수형 프로그래밍과 JavaScript ES6+>
https://www.inflearn.com/course/functional-es6/dashboard
함수형 프로그래밍과 JavaScript ES6+ - 인프런 | 강의
ES6+와 함수형 프로그래밍을 배울 수 있는 강의입니다. 이 강좌에서는 ES6+의 이터러블/이터레이터/제너레이터 프로토콜을 상세히 다루고 응용합니다. 이터러블을 기반으로한 함수형 프로그래밍,
www.inflearn.com
'JavaScript > 함수형 프로그래밍과 JavaScript ES6+' 카테고리의 다른 글
take, find (0) | 2021.08.24 |
---|---|
Array.prototype.join 보다 다형성이 높은 join 함수 (0) | 2021.08.24 |
range, map, filter, take, reduce 중첩 사용(개발자도구로 순서확인) (0) | 2021.08.20 |
L.map & L.filter (0) | 2021.08.20 |
제너레이터 / 이터레이터 프로토콜로 구현하는 지연 평가 (0) | 2021.08.20 |