프로그래밍/JavaScript

Currying에 대해 알아보자.

seungdols 2018. 2. 8. 23:20

자바스크립트 디자인 패턴 책의 내용을 정리한 내용입니다.
curring을 알기 전에 부분 적용이라는 개념을 먼저 알고 있어야 합니다.
사실, 많은 싸이트나 위키에서 curring을 잘못 받아들여 소개하기도 합니다. 일단은 제대로 이해하기 위해서 부분 적용이 뭔지 알아봅시다.

함수 적용

순수 함수형 프로그래밍에서는 함수를 호출하거나, 부른다고 하지 않고, 적용 된다고 표현합니다.
고로, apply로 이해하시는 것이 맞습니다.
자바스크립트에서도 Function.prototype.apply()를 사용하면 함수를 적용 할 수 있습니다.
  var sayHi = function(who) {
      return 'Hello' + (who ? ', ' + who : '') + '!';
  }
 
  sayHi();
  sayHi('world');
 
  sayHi.apply(null, ['world']);
apply()함수의 첫번째인자는 함수 내에 this와 바인딩할 객체이고, 두번째는 배열 또는 인자로 함수 내부에서 배열과 비슷한 형태의 arguments 객체로 사용 된다.
첫번째 인자가 null인 경우 this는 전역 객체를 가리키게 된다. 즉, 함수를 특정 객체의 메서드로가 아닌 일반적인 함수로 호출 할 때와 동일하다.
 
  var seungdols = {
      var sayHi = function(who) {
          return 'Hello' + (who ? ', ' + who : '') + '!';
      }
  }
 
  seungdols.sayHi('world');
  sayHi.apply(seungdols, ['world']);
또한 Function.prototype 객체에 call() 메서드도 있는데, apply()와 비슷한 기능을 하지만, 약간의 차이가 존재하는데, 함수의 매개변수가 하나 일경우에는 call()을 쓰는게 더 간편하다.
 
  sayHi.call(null, 'world');
위 코드상에서 쓰고자 한다면, 위와 같이 배열을 만들지 않고 쓰면 된다.

부분 적용

함수의 호출은 인자의 묶음을 함수에 적용하는 것으로 생각해볼 수 있다. 그렇다면, 인자의 일부만 적용시킬 수 있을까?
 
  var add = function(x, y) {
      return x + y;
  };
 
  add.apply(null, [5,6]);
 
  var newVal = add.partialApply(null, [5]);
  newVal.apply(null, [6]);
원래 목적은 add(5);하고 add(6); 호출 했을때, 결과값이 5 + 6 = 11 이 나오도록 하고 싶을 수 있다. 사실, 자바스크립트 함수는 우리가 원하는 방식으로 동작 하지 않는다. 다만, 위처럼 동작하도록 만들 수 있다. 함수가 부분적인 적용을 이해하고 처리 할 수 있도록 만드는 과정을 커링이라고 한다.
즉, 커링이 "인자 하나씩 받아 함수 시퀀스를 이용해 어떤 처리를 하는 것이다."라고 말하는 것은 오류라고 할 수 있다.
물론, 위키피디아 설명 - Currying의 경우에는 약간 모호하지만, 위와 같은 설명으로 되어있다.
In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument. Currying is related to, but not the same as, partial application.
위키피디아의 내용을 이해한대로 설명하자면, 어떤 함수가 여러 인자를 받거나 튜플 인자를 받는 함수인데,이를 인자 하나씩만 갖는 함수 시퀀스로 변환한 것을 말하며, 커링은 부분 적용과 관련이 있지만, 같은 것은 아니다.라고 말하고 있다. 하지만 이는 약간의 오류가 존재한다.
쉽게 말하면, 여러개의 인자를 받는 함수를 일부만 받아 적용할 수 있게 만드는게 커링인 것이고, 하나씩 받는 다고 해서 커링인것은 아닙니다.

Currying

커링은 수학자 하스켈 커리로부터 유래 되었고, 커링은 함수를 변형하는 과정이다.
커링은 이 변형 방법의 원래 발명가인 모세 쉔핀켈의 이름을 따 쉔핀켈화라고도 말한다.
 
  function add(x, y) {
      var oldx = x, oldy = y;
      if (typeof oldy === 'undefined') {
          return function(newy) {
              return oldx + newy;
          };
      }
      return x + y;
  }
  typeof add(4)
  "function"
  add(5)(5);
  10
위 코드를 간략하게 하는 방법도 존재한다.
 
  function add(x, y) {
      if (typeof y === 'undefined') {
          return function(y) {
              return x + y;
          };
      }
      return x + y;
  }
 
  function schonfinkelize(fn) {
      var slice = Array.prototype.slice, stored_args = slice.call(arguments, 1);
      return function() {
          var new_args = slice.call(arguments),args = stored_args.concat(new_args);
          return fn.apply(null,args);
      };
  }
 
  function add(x, y) {
      return x + y;
  }
 
  var testOperOne = schonfinkelize(add,6);
  testOperOne(10);//16
 
  schonfinkelize(add, 10)(20);//30
위와 같이 범용적으로 커링 할 수 있도록 하는 함수를 만들수도 있다.

커링을 사용해야 할 경우

어떤 함수를 호출할 때 대부분의 매개변수가 항상 비슷하다면, 커링의 적합한 후보라고 할 수 있다.

참고


반응형