반응형

 자바스크립트는 완벽한 함수형 프로그래밍 언어는 아니다. 함수형 프로그래밍을 더 맛보기 위해서는 lisp이나 haskell과 같은 언어를 사용해 보기 바란다. 함수형 프로그래밍은 함수의 조합으로 작업을 수행하는데, 이때 필요한 데이터와 상태는 변하지 않는다는 것이 중요하다. 변할 수 있는 것은 오로지 함수로, 이 함수가 연산의 대상이 된다.

 함수중에서 외부에 영향을 미치지 않는 것을 순수 함수(Pure Function)이라고 한다. 또한 함수를 하나의 값으로 간주하여 함수의 인자 혹은 반환값으로 사용할 수 있는 함수를 고계함수(Higher-order function)이라고 한다. 함수형 프로그래밍의 장점은 내부 데이터 및 상태는 그대로 둔 채 제어할 함수를 변경, 조합함으로써 원하는 결과를 내기 때문에, 높은 수준의 모듈화가 가능하다. 높은 수준의 모듈화가 가능하고 내부 데이터와 상태를 변경하지 않는다는 점은 병렬프로세싱에 엄청난 장점을 제공해 준다. (왜냐하면 락이 필요가 없기 때문이다.)

 자바스크립트는 1) 일급 객체로서의 함수, 2) 클로저 라는 특징 때문에 함수형 프로그래밍이 가능하다. 다음은 배열에서 함수를 적용해서 함을 구하는 함수형 프로그래밍의 예이다. 배열을 받아서 함수를 적용하고 적용한 값을 누적하는 것은 동일하며, 변하는 것은 적용하는(인자로 받은) 함수이다.

function reduce(func, arr, memo ){

var len=arr.length,i=0,accum=memo;

for(;i<len;i++){

accum=func(accum,arr[i]);

}

return accum;

 1. 더하기 함수 적용

var sum=function(x,y){return x+y;}

reduce(sum,[1,2,3,4],0);


2. 곱하기 함수 적용

var multiply=function(x,y){return x*y;}

reduce(multiply,[1,2,3,4],1);


[Memoization 패턴]

 예를 들어 피보나치 수열을 계산한다고 했을 때, 직관적으로는 다음과 같은 재귀적인 방식을 사용할 수 있다. 

function fibo(num){

return n<2 ? n : fibo(n-1)+fibo(n-2)

  이 함수를 한번 쓰고 버릴 것이 아니라면, Memoization 패턴을 이용하여 연산 속도를 줄일 수 있다. 예를 들어 1에서 10까지의 피보나치 수열을 구한다고 하면 중복된 연산을 많이 해야 한다. (피보나치 8과 피보나치 9를 사전에  계산하였다면 피보나치 10은 이 두 값을 그저 이용하면 된다.)  Memoization패턴은 앞서 연산한 결과를 캐시에 저장하여 새로운 연산을 하지 않고 그대로 활용하는 방법이다. 다음은 그 예이다.

var fibo=function (){

var memo=[0,1];

var fib=function(n){

var result=memo[n];

if(typeof result!=='number'){

result=fib(n-1)+fib(n-2);

memo[n]=result;

}

return result;

};

return fib;

}();

 다음은 이런 memoization을 일반화해서 적용할 수 있는 함수이다.

var memoizer = function(memo,func){

var shell=function(n){

var result=memo[n];

if(typeof result !=='number'){

result=func(shell,n);

memo[n]=result;

}

return result;

};

return shell;

}; 

 이를 이용해서 피보나치 수열과 Factorial을 구하는 것은 다음과 같이 적용 가능하다.

var fibo=memoizer([0,1],function(shell,n){

return shell(n-1)+shell(n-2);

});

var fact=memoizer([1,1],function(shell,n){

return n*shell(n-1);

}); 


[Curry 패턴]

 커링은 함수와 인수를 결합하여 새로운 함수를 만들 수 있게 한다. 예를 들어 두개의 인자를 받는 add 함수가 있다고 하면 두 인자중 하나를 고정시켜서 더해주는 함수를 만든다고 하면, 다음과 같이  Curry 함수를 적용한다고 할 수 있다. 

function add(x,y){

return x+y;

}

var add1=curry(add,2);

add1(6) //이 값은 8이 된다. 

curry 함수는 다음과 같다.

function curry(func){

var args=Array.prototype.splice.call(arguments,1); // 첫번째 인자인 함수명은 제외

return function(){

//args에 들어오는 인자를 붙임, 클로저

return func.apply(null,args.concat(Array.prototype.slice.call(arguments)));

}

 curry는 bind함수를 이용해서 구현 가능하다. 상기 예는 다음과 같이 bind함수로 활용 가능하다.

 var add1=add.bind(this,2);

add1(6) // 이 값은 8이 된다.



반응형
Posted by alias
,