이터러블을 까먹었다면? → 이터러블 연구소
const map = (f, iter) => {
if (!iter[Symbol.iterator]) {
return;
}
const res = [];
for (const value of iter) {
// iterator를 순회하며 콜백함수를 실행후 결과에 저장
res.push(f(value));
}
return res;
};
const filter = (f, iter) => {
const res = [];
for (const value of iter) {
if (f(value)) {
res.push(value);
}
}
return res;
};
const reduce = (f, iter, acc) => {
if (!acc && typeof acc != "number") { // acc 비교부분 수정필요 인덱스값도 사용하고 싶어
iter = iter[Symbol.iterator]();
acc = iter.next().value; // acc가 없을 경우 acc를 만들어 iterable를 한번 next함
}
for (const value of iter) {
acc = f(acc, value); // 이터러블 순회하며 acc에 누적
}
return acc;
};
이터러블을 받아 순회한다.
reduce에서는 누적값이 없을경우 이터레이터를 한번 순회하여 초기값을 이터러블의 첫번째 인자로 사용하는 방식으로 구현함
const go = (...args) => reduce((acc, currFunc) => currFunc(acc), args);
// 인자들을 받는다. 인자들을 순회하며 reduce로 누적하는데,
// 초기값이후 인자로 받은 함수들을 순차적으로 실행하며 누적한다.
ex) go(
0,
(a) => a + 1,
(a) => a + 10,
(a) => a + 100
) // 111
const pipe = (...funcs) => (value) => go(value, ...funcs/*스프레드 문법없을시 funcs는 배열이므로 에러*/);
// 파이프 함수 특징은 클로저라는 점이다.
// 인자로 함수들을 받고 이후 함수를 리턴한다.
// 리턴한 함수로부터 value를 받아 go 함수를 통해 순차적으로 함수들을 적용한다.
// 함수들을 합성하는데 용이하다.
------- 문제점 ------
// 무엇이 문제일까?
const problem = pipe((a,b)=> a + b, (a)=> a + 1)
problem(1, 2); // 결과는?
//문제점은 현재 파이프함수가 인자가 하나일 경우만을 고려하여 짜여졌다는 점이다.
// 1. problem 자체는 문제가 없지만 인자 1, 2중 1만이 넘어가게 되어 결과는 NaN이된다. 1 + undefined
// 해결책으로 (a, b)=>a + b 를 add란 이름으로 빼내어 problem(add(1,2)) 로도 가능하지만 가독성이 떨어진다.
// 해결책
const pipe = (f,...funcs) => (...values) => go(f(...values),...funcs))
// pipe함수가 리턴한 클로저 함수를 실행할때 go의 첫번째 인자는 처음받은 함수들중 첫번째 함수가 적용된다.
// 이후 클로저의 인자들을 모두 적용하여 계산을 진행한다.
const curry = (f) => (arg, ...rest) =>
rest.length ? f(arg, ...rest)
: (...oneMoreArgs) => f(arg, ...onemoreArgs)
// 커리 함수는 인자에 따라 클로저함수의 리턴값이 달라진다.
// 커리 함수는 함수를 받아 저장하고 클로저 함수를 리턴한다.
// 클로저 함수는 인자가 2개 이상 경우 저장한 함수를 즉시 실행한다.
// 클로저 함수의 인자가 1개일 경우 한번더 함수를 리턴하여 인자를 받아 함수를 실행하게 된다.
const 곱하기 = curry((a, b)=> a * b);
곱하기(1, 2); // 인자가 2개 이상이므로 저장한 첫번째 콜백함수가 실행되어 2가 나옴
곱하기(1)(2); // 클로저인 곱하기의 인자가 1개였으므로 함수를 리턴함,
// 리턴한 함수에 다시 인자를 받아 저장했던 콜백한수를 실행