Range 함수
const range = (l) => {
  let i = -1;
  let res = [];
  while (++i < l) {
    res.push(i);
  }
  return res;
};Range 함수 실행 후, 모든 값을 더하는 함수
- reduce함수로- list를 전달하기 전에, 이미- range에서 코드가 평가되어- 배열로 리턴됨
- 사실 redudce가 작동하기 전까지는range로 리턴된 배열은 필요한 상태가 아님
- reduce가 순회를 시작하고 하나의 값으로 데이터를 축약 할 때, 그 때- list가 필요한 것
const add = (a, b) => a + b;
const range = (l) => {
  let i = -1;
  let res = [];
  while (++i < l) {
    res.push(i);
  }
  return res;
};
const list = range(4); // 이미 평가가 끝나서 배열로 리턴됨
console.log(reduce(add, list));느긋한 L.Range
- const list = L.range(4)코드 평가시- L.range내부- while문은 실행하지 않음
- list.next()가 실행 했을 때,- while문이 실행됨
- 즉, 밑에 list는 배열상태로 있지 않음(L.range {<suspended>})
- reduce에서 해당 값들이 필요할 때,- while문이 작동하면서 하나씩 코드가 평가됨
- L.range에서는 Array을 만들지 않고 reduce가 돌면서 하나씩 값을 꺼내는 방식임
- ex) while문이 돌면서list.next().value으로 값을 꺼냄
const L = {};
L.range = function* (l) {
  let i = -1;
  while (++i < l) {
    yield i;
  }
};
const list = L.range(4);
console.log(reduce(add, list));Reduce 내부 함수를 통해 Range와 L.Range 비교
- 위 Range는 reduce를 실행했을 때,Array를 만들고 →Iterator를 만들고 그리고 순회하면서next()로 값을 얻어서 축약 함
- 그런데 L.Range같은 경우 reduce를 실행 했을 때,Iterator를 만들고 → iterator가 자기 자신을 리턴하는 Iterable이고 해당하는 함수를 실행하면 이미 만들어진 Iterator를 리턴만 하고 그 다음 순회를 진행
- 그래서 일반 Range보다는 L.Range가 조금 더 효율 적임
const reduce = curry((f, acc, iter) => {
  if (!iter) {
    iter = acc[Symbol.iterator]();
    acc = iter.next().value;
  }
  for (const a of iter) {
    acc = f(acc, a);
  }
  return acc;
});L.range와 range 성능 테스트
function test(name, time, f) {
  console.time(name);
  while (time--) f();
  console.timeEnd(name);
}
// 테스트 결과
// L.range: 257.204833984375ms
// range: 489.680908203125ms
test('range', 10, () => reduce(add, range(1000000)));
test('L.range', 10, () => reduce(add, L.range(1000000)));느낀점
정말 이번 학습을 통해서 그냥 아무 생각 없이 당연하게 사용했던 함수들을 다시 한번 생각해본 시간이였으며,
단순히 구현에 만족하면서 코드를 작성하고 있음을 반성하게 되었다.
또한 코드의 성능을 높일 수 있는 방법을 알게 되었다.
이번 강의 학습을 통해, 아주 작은 디테일이 이렇게도 큰 차이를 만들 수 있다라는 사실과 이러한 디테일이 나중에는 사용자에게 더 좋은 서비스를 제공할 수 있지 않을까 생각을 해보았다.
참고
유인동님의 함수형 프로그래밍과 JS ES6+ 강의