본문 바로가기

Programming/Javascript

15. Javascript 함수형 프로그래밍 적용(1) - 필수 선행지식 + 커링(curry) 1

javascript logo image

 

 

앞서 살펴본 함수형 프로그래밍 기법을 통해, 현재 통용되는 몇 가지 함수를 재구현하거나 구조를 응용해 보도록 하겠습니다. 우선, 이 과정을 위해서는 몇 가지 잊어서는 안 되는 선행 지식들이 있는데, 커링을 구현하면서 차례로 같이 살펴보도록 하겠습니다. 

 

 


 

 

우선 '커링'을 먼저 정의해 보겠습니다. 커링은 "특정 함수에서 정의-선언된 파라미터의 값 일부를 고정하고, 나머지 파라미터에 전달된 인자로 받는 함수를 생성하는 것"을 의미합니다. 우선 예제 코드를 먼저 살펴보고, 여기에 필요한 몇 가지 선행지식에 대한 설명부터 진행하겠습니다. (물론, 다 알고 있어야 하는 내용이지만 해당 내용을 정리하는 제가 머리가 나빠서 다 잊어버렸더라구요...ㅠ)

 

 

function calculate(a, b, c) {
    return a * b + c;
}

function curry(func) {
    var args = Array.prototype.slice.call(arguments, 1);

    console.dir(args);

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

var new_func1 = curry(calculate, 9);
console.log(new_func1(2,3));

var new_func2 = curry(calculate, 9, 3);
console.log(new_func2(3));

 

 

일단, 우리는 여기서 apply 함수에 대해서 먼저 짚고 넘어가려고 합니다. 이미 유사배열 객체에 대해서 다루면서 Javascript 특유의 call / apply 함수에 대해서 배운 적이 있습니다. 첫 번째 파라미터는 호출 함수의 this에 바인딩되는 객체라고 설명했고, 다음 파라미터는 해당 호출 함수에 전달되는 인자라고 정의되었죠.

 

여기서 call과 apply의 차이점을 기술적으로 정의할 때, 파라미터 값을 직접 입력하느냐(call) 혹은 배열 형태로 전달하느냐(apply)로 구분했었습니다. 여기서는 함수형 프로그래밍의 관점에서 apply를 주로 사용하게 되는데, 함수를 적용한다('applying functions')는 개념은 함수형 프로그래밍에서 단순 in-out 개념을 넘어서 인자나 리턴 값으로 전달된 '함수'를 어떠한 데이터에 적용하는 의미로 사용되었다고 이해하면 되겠습니다. 

 

 


 

 

그다음, arguments에 대한 내용입니다. 이미 함수 초반에 다루었던 내용이지만 다시 한번 리뷰해 보겠습니다. arguments는 어떠한 함수를 실행하게 되면 함수 실행 시 파라미터로 전달된 인자 값들이 저장되는 배열 객체입니다. 단! 주의해서 기억해야 할 것은 이 arguments는 "배열"이 아니라는 점이었죠? 다시 한번 기억을 더듬어 봅시다. arguments에는 length 프로퍼티가 없기 때문에, 인덱스 값에 저장되는 배열 형태의 객체이지만 배열 공통 메서드를 사용할 수 없다고 했습니다. 그래서 바로 slice( )와 같은 배열 메서드를 사용하기 위해서는 apply를 사용하는 것이라고도 설명드렸습니다. 

 

 


 

 

그럼 다음 코드를 한 번 해석해 보도록 하겠습니다.

 

    var args = Array.prototype.slice.call(arguments, 1);

 

curry라는 함수가 어떠한 함수를 인자로(func) 받아 실행하는 것으로 선언되어 있습니다. 그리고 그 안에서 변수 args는 어떠한 값들을 받는 배열 객체입니다. 여기서 보면, call을 통해서 slice( ) 메서드를 실행합니다. 여기서 인자 값 arguments와 1은 고정되어 사용하게 됩니다. 

 

실제로 이 코드가 어떻게 작동할까요? 아래 실행문을 기준으로 설명드리겠습니다. 

 

var new_func1 = curry(calculate, 9);

 

위와 같이 curry 함수를 실행하게 되면, args에서는 일단 arguments에는 어떤 값들이 저장될까요? 바로 인자로 받은 함수 caculate와 정수 9가 저장됩니다. 배열 형태이므로, 인덱스 0에는 caculate / 인덱스 1에는 9가 저장되어 있습니다. 그런데, 여기서 arguments에 slice 함수가 실행됩니다. slice에서 두 번째 파라미터로 전달된 1은 어떤 의미일까요? 바로 arguments의 인덱스 1번 요소부터 잘라내 저장한다는 의미가 됩니다. 다시 말해 calculate(인덱스 0)을 제외한 모든 원소가 args에 저장된다는 것이죠.

 

 

Array.prototype.slice() - JavaScript | MDN

slice() 메서드는 어떤 배열의 begin 부터 end 까지(end 미포함)에 대한 얕은 복사본을 새로운 배열 객체로 반환합니다. 원본 배열은 바뀌지 않습니다.

developer.mozilla.org

 

*15. Javascript 함수형 프로그래밍 적용(1) - 필수 선행지식 + 커링(curry) 2로 이어집니다.