[Functional Programming] - 함수형 자바스크립트의 실용성.

Inevitable.Jason·2021년 3월 11일
0
post-thumbnail

Intro.

성공적인 프로그래밍?

좋은 프로그램의 척도에는 "사용성", "성능", "확장성", "기획변경" 에 대한 대응력 등이 있으며, 이것들을 효율적이고 생산적으로 이루는 일이 성공적인 프로그래밍이다.

함수형 프로그래밍은 성공적인 프로그래밍을 위해 부수 효과를 최대한 멀리하고 조합성을 강조하는 프로그래밍 패러다임이다.

addMaker

  • currying 또는 partial code.a
  • 함수로 함수를 리턴.
  • add5 의 parameter a는 불변.
  • addMaker 가 return 한 익명함수는 closure.
function addMaker (a) {
  return function (b) {
    return a + b;
  }
}
addMaker(10)(5); // 15
let add5 = addMaker(5)
add5(3); // 8
add5(5); // 10
function add (a, b) {
	return a + b;
}

이렇게 두가지의 function (addMaker, add) 을 본다면,
parameter a는 불변하고 상수로 쓰인다.

함수형 자바스크립트의 실용성 기초 개념.

절차지향적으로 작성된 코드를 함수형으로 변경하면서 함수형 자바스크립트의 실용성을 알아 보자.

filter 보조함수를 통한 조합.

let users = [
  { id: 1, name: 'ID', age: 32 },
  { id: 2, name: 'HA', age: 25 },
  { id: 3, name: 'BJ', age: 32 },
  { id: 4, name: 'PJ', age: 28 },
  { id: 5, name: 'JE', age: 27 },
  { id: 6, name: 'JM', age: 32 },
  { id: 7, name: 'HI', age: 24 },
];

이러한 users table 이있다고 가정해보자.

// 1. 유저중에 age 가 30 미만인 유저를 출력
let temp_users = [];
let len = users.length;
for (let i = 0; i < len; i++) {
  if (users[i].age < 30) temp_users.push(users[i]);
}
console.log('temp', temp_users.length); // 4
// 2. 30 미만인 유저의 나이를 출력
let ages = [];
for (let i = 0; i < temp_users.length; i++) {
  ages.push(temp_users[i].age);
}
console.log('ages', ages);
// 3. user 중에 age 가 30 이상인 유저를 출력
let temp_users = [];
for (let i = 0; i < users.length; i++) {
  if (users[i].age >= 30) temp_users.push(users[i]);
}
console.log(temp_users.length);
// 4. age 가 30 이상인 유저의 이름을 출력
let names = [];
for (let i = 0; i < temp_users.length; i++) {
  names.push(temp_users[i].name);
}
console.log(names);

이렇게 필터링을 할수있지만, 위 코드에서 함수형으로 Refactoring 해보자. 중복된 코드들을 뺀다면 훨신 가독성 좋고 짧은 코드를 만들어낼 수 있다.

함수형 프로그래밍에서는 "항상 동일하게 동작하는 함수" 를 만들고 보조함수를 조합하는식으로 조합을 완성한다.

보조함수

function filter(list, predicate) { // 이 함수의 if문은 predicate의 결과에 의존하게 된다.
    let new_list = [];
    let len = list.length;
    for (let i = 0; i<len; i++){
      if(predicate(list[i])) new_list.push(list[i])
    }
    return new_list;
}

이렇게 보조함수를 만들어서 사용한다면,

let users_under_30 = filter(users, function (user) { // 30세 미만의 갯수
  return user.age < 30;
});
console.log(users_under_30.length); // 4

let ages = [];
for (let i = 0; i < users_under_30.length; i++) { // 30세 미만 각각의 나이
  ages.push(users_under_30[i].age);
}
console.log(ages); // [25, 28, 27, 24]

let users_over_30 = filter(users, function (user) { // 30세 이상
  return user.age >= 30;
});

console.log(users_over_30.length); // 3

let names = [];
for (let i = 0; i < users_over_30.length; i++) {
  names.push(users_over_30[i].name);
}
console.log(names);  // [ 'ID', 'BJ', 'JM' ]

이 보조 함수를 통해 코드가 짧아지고 재사용성이 보다 높은 함수 filter가 생겼다.

map 보조함수

function filter(list, predicate) {
  let new_list = [];
  let len = list.length;
  for (let i = 0; i < len; i++) {
    if (predicate(list[i])) {
      new_list.push(list[i]);
    }
  }
  return new_list;
}

const map = (list, itaratee) => {
  let new_list = [];
  for (let i = 0; i < list.length; i++) {
    new_list.push(itaratee(list[i]));
  }
  return new_list;
};

let users_under_30 = filter(users, function (user) {
  return user.age < 30;
});

console.log(users_under_30.length); /// 4

let ages = map(users_under_30, function (user) {
  return user.age;
});
console.log(ages); // [ 25, 28, 27, 24 ]

let users_over_30 = filter(users, function (user) {
  return user.age >= 30;
});

console.log(users_over_30.length); // 3

let names = map(users_over_30, function (user) {
  return user.age;
});

console.log(names); // [ 32, 32, 32 ]

filter와 map 을 사용함으로서, 코드가 매우 단순해졌다 for도 없고 if 도 없다.

함수 중첩

filter와 map 을 중첩해서 사용하면 변수할당을 모두 제거하고 원하는 값을 출력할수있다.


function log_length(value) {
  console.log(value.length);
  return value;
}

console.log(
  log_length(
    map(
      filter(users, function (user) {
        return user.age < 30;
      }),
      function (user) {
        return user.age;
      }
    )
  )
);
// 4
// [ 25, 28, 27, 24 ]

console.log(
  log_length(
    map(
      filter(users, function (user) {
        return user.age >= 30;
      }),
      function (user) {
        return user.age;
      }
    )
  )
);
// 3
// [ 32, 32, 32 ]

이로서 처음 만든 for문으로 필터링을 하는 방식과 함수형프로그래밍을 통해 "같은동작을 하는 함수" + "보조함수" 를 통한 리팩토링을 비교해보았다.

다음편에서 계속....

profile
Who wanna be a programming nerd.

0개의 댓글