[JS] 커링(Currying)과 함수 조합(Compose)

0
post-thumbnail

함수는 인자로 함수를 받을 수 있다.커링 함수는은 함수 인자로 받으면 기능이 변화된 새로운 함수를 반환한다. 커링 패턴을 통해 함수 인자를 분리하여 함수를 재사용 가능하게끔 만들 수 있다.

function add(a,b){
  return a+b;
}


function multiply(a, b) {
  return a*b
}

function multiplyX(x){
  return function (a) {
    return multiply(a,x);
  }
}

const multiplyTwo = multiplyX(2);
const multiplyThree = multiplyX(3);


const multiplyTwo = multiplyX(2);
multiplyTwo(3); //multiply(2,3)과 동일하게 동작

위 예제 코드에서 처럼 함수를 반환함으로써 multiply함수를 분리해서 작성할 수 있다.

const formula = x => addFour(multiplyThree(multiplyTwo(x)));
const formula = x => addX(4)multiplyX(3)(multiply2(x)));

하지만 이 경우 함수 인자의 가장 안쪽에 있는 것부터 수행되며 결과값을 반환하기 때문에 순서가 뒤 바뀌거나 하게 되면 결과값에 오류가 발생할 수 있다. 그럼 이 가독성 문제를 어떻하면 해결할 수 있을까?
계산이 되는 순서대로 함수를 배치하면 함수를 사용하기도, 읽기도 편한 코드가 되지 않을까?
입력한 함수의 순서대로 조합하는 함수를 reduce를 통해 구현할 수 있다.
reduce에 두번째 인자에는 보통 최종 결과 데이터의 형태를 넣는데, 지금은 함수를 반환해야 하기 때문에 함수를 반환해주었다.

Compose 함수

function compose(...args) {
  return args.reduce(function(prevFunc, nextFunc) {
    return function(...values) {
      return nextFunc(prevFunc(...values));
    }
  }, k => k);
}

/// (((x * 2) + 5) * 3) + 4

const formula = compose(
  multiplyX(2),
  addX(5),
  multiplyX(3),
  addX(4),
);
  
formula(10);

step1

  • prevFunc: k => k
  • nextFunc: multiplyTwo
  • 반환값1
function(x){
  return multiplyTwo((k=> k)(x));
}

step2

  • prevFunc: 반환값1
  • nextFunc: multiplyThree
  • 반환값2
function(x){
  return multiplyThree(반환값1)(x));
}

step3

  • prevFunc: 반환값2
  • nextFunc: addFour
  • 반환값3
function(x){
  return addFour(반환값2)(x));
}

참고
커링과 함수 조합 파헤치기

0개의 댓글