함수형 프로그래밍 2주차

강석우's avatar
Oct 07, 2024
함수형 프로그래밍 2주차

섹션 5. 코드를 값으로 다루어 표현력 높이기

go

go 함수란?

인자를 받아 결과를 바로 산출해내는 함수이다.

첫번째 인자는 시작되는 값을 받고, 나머지는 함수를 받아 인자가 함수들에 순차적으로 돌아가며 결과가 만들어지게 실행된다.

go 함수 내부 코드

const go = (...args) => reduce((a, f) => f(a), args);

// 예시
go(
  add(0, 1), // 1
  (a) => a + 10, // 11
  (a) => a + 100, // 111
  console.log // 111을 콘솔로 찍음
);

왜 쓰는거야?

아래와 같이 map, filter, reduce 가 중첩된 함수가 있다고 가정하자

 reduce(
    add,
    map(
      (p) => p.price,
      filter((p) => p.price < 20000, products)
    )
  )

이해하기도 어렵고 보기도 힘들다.
그렇다면 go 함수로 나타내면 어떻게될까?

go(
  products,
  (products) => filter((p) => p.price < 20000, products), // 20000 미만인 상품들
  (products) => map((p) => p.price, products), // 20000 미만인 상품들의 가격
  (prices) => reduce(add, prices), // 20000 미만인 상품들의 가격 총합
  log
);

코드가 길어지는 것 같지만 가독성이 훨씬 좋아졌다. ( 뒤에 코드를 줄이는 방법은 curry를 통해 설명한다. )

pipe

pipe 함수란?

pipe 함수는 인자를 받아 함수를 리턴해주는 함수이다.
함수자체를 반환하여 최종적으로 인자값으로 받은 함수리스트를 합성해서 합성된 합수를 가지고 로직을 수행한다.

pipe 함수 내부코드

const pipe =
  (f, ...fs) =>
  (...as) =>
    go(f(...as), ...fs);

// 예시
const f = pipe(
  (a, b) => a + b,
  (a) => a + 10,
  (a) => a + 100
);

console.log(f(0, 1)); // 111

중복되는 코드 제거

pipe 함수를 통해 go 함수의 중복되는 코드를 제거할 수 있다.

go(
  products,
  (products) => filter((p) => p.price < 20000, products), // 20000 미만인 상품들
  (products) => map((p) => p.price, products), // 20000 미만인 상품들의 가격
  (prices) => reduce(add, prices), // 20000 미만인 상품들의 가격 총합
  log
);

const total_price = pipe(
  map((p) => p.price),
  reduce(add)
);

// map, reduce를 total_price로 합침
go(
  products,
  (products) => filter((p) => p.price < 20000, products), // 20000 미만인 상품들
  total_price,
  log
);

curry

curry 함수란?

여러 개의 인자를 가진 함수를 호출 하는 경우, 파라미터의 수보다 적은 수의 파라미터를 인자로 받으면 누락된 파라미터를 인자로 받는 기법.
다시말해, 부분적으로 적용된 함수를 체인으로 계속 생성해서 결과적으로 값을 처리하도록 하는것이 본질이다.

const curry =
  (f) =>
  (a, ..._) =>
    _.length ? f(a, ..._) : (..._) => f(a, ..._);

// 예시
const mult = curry((a, b) => a * b);

console.log(mult(2)); // (..._) => f(a, ..._) => 나머지 인자를 더 전달했을 때, 함수에게 받어두둔 인자와 함께 실행
console.log(mult(1)(2)); // 2

const mult3 = mult(3); // 첫 인자가 3으로 고정된 mult 함수
console.log(mult3(10)); // 30
console.log(mult3(5)); // 15
console.log(mult3(3)); // 9

위와 같이 curry를 통해 map, filter, reduce를 선언해준 뒤에 아래와 같이 작성할 수 있다.

go(
  products,
  (products) => filter((p) => p.price < 20000)(products),
  (products) => map((p) => p.price)(products),
  (products) => reduce(add)(products),
  console.log
);
// 또 아래와 같이 다시 한번 줄일 수 있다.
go(
  products,
  filter((p) => p.price < 20000),
  map((p) => p.price),
  reduce(add),
  console.log
);

Share article
RSSPowered by inblog