함수형 프로그래밍 - 명령형 습관 지우기

MyeonghoonNam·2021년 8월 14일
1

함수형 프로그래밍

목록 보기
7/10

함수형 프로그래밍 시리즈 내용으로 계속 이어서 내용이 진행되므로 처음 부터 포스팅을 확인해주세요.

map과 filter를 활용한 reduce

const users = [
  {name:'AA', age: 35},
  {name:'BB', age: 26},
  {name:'CC', age: 28},
  {name:'CC', age: 34},
  {name:'EE', age: 23},
]

// 1
console.log(
  reduce((total, u) => total + u.age, 0, users));

const add = (a, b) => a + b;

// 2
console.log(
  reduce(add, L.map(u => u.age, users)));

const ages = L.map(u => u.age);

// 3
console.log(
  reduce(add, ages(users)));

// 4
console.log(
  reduce((total, u) => u.age >= 30 ? total : total + u.age,
  0,
  users)
);

// 5
console.log(
  reduce(add,
    L.filter(n => n < 30,
      L.map(u => u.age, users)))
);

코드에서 첫 번째 console.log를 보면 total과 u.age라는 서로 다른 형태를 통해 합산을 하는 것을 알 수 있는데, reduce에서 서로 합산 할 때는 서로 형이 같아야지 더 간단하며 좋은 코드라고 할 수 있다.

다시 말해서, 하나의 보조함수에서 복잡하게 처리하는 것 보다, reduce에 집어넣기 전에 데이터를 통일 시켜서 연산하는 것이 더 좋은 코드라는 말이다.

두 번째 console.log와 같이 형이 같은 인자가 두 개 들어오는 함수의 경우에는 세 번째 console.log 처럼 심플하게 코드를 짤 수 있다.

네 번째 console.log와 같이 조건이 더 추가된 경우에는 filter를 섞어서 코드의 복잡성을 다섯 번째 console.log 처럼 줄일 수 있다.

reduce하나를 사용해서 복잡하게 사용하는 것보다, reduce와 map이나 filter를 같이 사용해서 하나의 형태를 사용하는 인자로 만들어서 사용하는 것이 다형성을 통한 함수의 재사용성 등 에서 훨씬 유리하고 이터러블 프로그래밍을 더 잘하게 되는 방법이 될 것 이다.


Object To Query

const obj = {
  a: 1,
  b: undefined,
  c: 'CC',
  d: 'DD'
};
// a=1&c=CC&d=DD 의 형태를 출력하게 구현하기

function query1(obj) {
  let response = '';

  for(const k in obj) {
    const v = obj[k];

    if(v === undefined) continue;
    if(response !== '') response += '&';

    response += `${k}=${v}`;
  }

  return response;
}

console.log(query1(obj));

function query2(obj) {
  return Object
    .entries(obj)
    .reduce((query, [k, v], i) => {
      if(v === undefined) return query;

      return `${query}${i > 0 ? '&' : ''}${k}=${v}`;
    }, '');
}

console.log(query2(obj));

const query3 = obj =>
  join('&',
    map(([k, v]) => `${k}=${v}`,
      filter(([k, v]) => v !== undefined, Object.entries(obj))))

console.log(query3(obj));

const query4 = pipe(
  Object.entries,
  L.filter(([k, v]) => v !== undefined),
  L.map(join('=')),
  join('&')
)

console.log(query4(obj));

명령형으로 구현된 query1 부터 함수형으로 표현한 query4 까지를 통해서 우리는 단순 reduce를 활용이 아니라 map, filter를 함께 활용한 go, pipe, curry의 구현으로 훨씬 표현력이 좋은 코드를 볼 수 있다.


Query To Object

이번엔 위와 반대로 Query를 Object 형태로 바꾸어가며 비교해보자.

const split = curry((sep, str) => str.split(sep));

const queryToObject = pipe(
  split('&'),
  L.map(split('=')),
  L.map(([k, v]) => ({[k] : v})),
  reduce(Object.assign)
)

console.log(queryToObject('a=1&c=CC&d=DD'));

마찬가지로 reduce, map, filter를 적절히 활용하여 표현력이 좋은 코드 작성이 가능하다.

profile
꾸준히 성장하는 개발자를 목표로 합니다.

0개의 댓글