자바스크립트에서 커링(Currying)은 반환값이 함수인 함수를 의미한다. 커링은 함수 자체를 재활용하기 위한 방법이다. 예를 하나 살펴보자.
function equation(a, b, c) {
return (function (x) {
return (((x*a)*b) + c);
});
}
equation 함수는 (x*a)*b +c를 계산하는 함수를 반환하는 커링 함수다. 위의 커링함수의 사용 방법은 아래와 같다.
var answer = equation(2, 3, 4)(1);
자바스크립트를 다루다보면 함수에 인자를 전달하는 괄호가 두 번 연속해서 사용된 경우가 있는데 이는 커링함수를 호출한 것이다. 겉을 감싸고 있는 equation 함수에 인자 (2, 3, 4)를 전달하면 (x*2)*3 + 4를 계산하는 함수가 반환되고 이 함수에 다시 인자 1을 전달해서 1*2*3 + 4를 계산한다.
커링의 개념과 사용 방법이 궁금하다면 여기까지 읽으면 된다. 이어지는 내용은 커링 함수를 왜 사용하는가에 관한 내용이다.
커링은 함수 자체를 재활용하기 위한 방법이다. 아래 두 함수 multiply, add 함수는 각각 두 수를 곱하고 더한 결과를 반환한다.
const multiply = (a, b) => {return (a*b);}
const add = (a, b) => {return (a+b);}
이 두 함수를 이용해서 각각 4증가, 2배수 함수를 아래와 같이 만들 수 있다.
const addFour = (x) => {return (add(4, x));}
const mulTwo = (x) => {return (multiply(2, x));}
위와 같이 커링을 활용하면 multiply, add 함수를 사용해서 더 다양한 계산식을 함수로 만들 수 있다.
예를 들면 아래와 같이 (2*x)+4를 커링을 이용해서 하나의 함수로 만들 수 있다.
const mulTwoAddFour = (x) => {return (addFour(mulTwo(x)));}
아래와 같이 3을 곱하는 커링 함수를 하나 더 정의하자.
const mulThree = (x) => {return (multiply(3, x));}
수식 ((2*x) + 4)*3을 아래와 같이 커링 개념을 이용해서 만들 수 있다.
const mulTwoAddFourMulThree = (x) => {return(mulThree(addFour(mulTwo(x))));};
커링을 이용한 함수의 재활용 예를 살펴보았다. 이어지는 내용은 함수들을 중첩하여 적용한 결과를 반영하는 새로운 함수인 compose() 함수를 만드는 내용이다. 사실 커링을 이해하는 데 필수적인 개념은 아니고 이를 응용한 예이기 때문에 관심있는 독자분들께서 읽어보면 된다.
위 예에서 함수의 이름은 mulTwoAddFourMulThree이지만 함수의 내용을 보면 mulThree(addFour(mulTwo(x)))와 같이 이름과는 반대 순서로 되어 있다. 함수를 인자로 주면 순서대로 조합해서 반환하는 compose() 함수를 만들면서 커링 개념을 응용해보자.
자바스크립트에서 Array 객체의 reduce 메서드(Array.prototype.reduce())는 주어진 배열의 각 요소에 대해 리듀서(reducer) 함수를 실행시켜 배열을 하나의 값으로 요약한다. 즉, reduce의 뜻 그대로 줄이는 것이다. 이 reduce 메서드를 이용하면 함수들을 하나로 조합할 수 있다.
reduce 메서드를 아래와 같이 사용할 수 있다.
Array.reduce('리듀서 함수', initialValue='초기값');
reduce 함수의 사용 예를 하나 살펴보자. 아래 예는 1, 2, 3, 4로 이루어진 배열의 합을 reduce 함수를 이용해서 구한것이다.
const testArr = [1, 2, 3, 4];
const testReducer = (acc, cur) => {return(acc + cur);}
testArr.reduce(testReducer, initialValue=0); // 결과 = 1+2+3+4 = 10
reduce함수가 주어진 배열을 축소하기 위해 사용하는 리듀서reducer 함수(위의 예에서는 testReducer)는 네 개의 인자를 받는 (콜백)함수이다. 함수는 아래와 같이 생겼다.
reducer(acc, cur [, idx] [, src])
reducer 함수에서 세 번째 인자인 idx는 처리할 요소의 시작 인덱스 값이고, 네 번째 인자인 src는 처리 대상이 되는 배열이다. 값을 지정하지 않으면 reducer함수는 자신을 호출한 배열의 첫 번째 요소에서 부터 reducer함수를 적용한다. 보통 이 세 번째 네 번째 인자는 값을 지정하지 않고 사용한다.
reduce 메서드는 reducer 함수가 실행되면 그 결과값이 acc인자를 통해 다시 입력되도록 만들어 준다. 위의 예에서 보면 첫 번째 인덱스의 값인 1과 초기값(initialValue) 0을 더한 값이 인덱스의 두 번째 값인 2를 계산할 때 acc인자를 통해 전달되어 1 + 2가 reducer함수의 결과로 반환되고 이 값은 다시 acc를 통해 다음 계산에 반영된다. 이 과정은 배열의 각 값에 대해 반복된다.
함수들을 입력 인자로 받고 커링 개념을 이용하여 이들 함수들을 결합하는 compose 함수를 만들어보자.
function compose(...arg) {
function reducer(acc, cur) { // ①
return(
function(x) {
return(cur(acc(x)));
}
);
}
function initFunc(x) { // ②
return(x);
}
return (arg.reduce(reducer, initialValue=initFunc)); // ③
}
① 리듀서 함수는 앞서 실행했던 결과인 acc(x)를 현재 주어진 함수인 cur(x)에 대입한 결과를 반환하는, 즉 함수를 반환하는 커링 함수다.
② 입력을 그대로 반환하는 함수를 정의하였다. reduce 메서드의 초기값으로 사용된다.
③ 구조 분해 할당 구문인 ...arg로 함수 안에서 인자들을 array 형태로 가져올 수 있다. array의 reduce() 메서드를 호출하고 reducer함수로는 ①에서 정의한 함수를, 초기 acc값으로는 ②에서 정의한 함수를 주어 인자의 함수들을 중첩시킨다.
이 compose 함수가 동작하는지 확인해보자.
const mulTwoAddFourMulThree = (x) => {return(mulThree(addFour(mulTwo(x))));};
mulTwoAddFourMulThree(2); // 결과: 24
const composedMulTwoAddFourMulThree = compose(mulTwo, addFour, mulThree);
composedMulTwoAddFourMulThree(2); // 결과: 24
참고로 화살표 함수를 이용해서 compose함수를 아래와 같이 기술할 수 있다.
const compose = (...arg) => {
const reducer = (acc, cur) => {return((x) => cur(acc(x)));}; // ①
const initFunc = (x) => {return(x);}; // ②
return (arg.reduce(reducer, initialValue=initFunc)); // ③
};
■
'프로그래밍 언어 | 컴퓨터 관련' 카테고리의 다른 글
[React] React Router v5 → v6 변경 내용 적용 예 (0) | 2021.11.15 |
---|---|
비대칭 키 암호화 구조 (0) | 2021.10.22 |
[Python] 멀티 프로세스 환경에서 file, db 등 자원 관리 (0) | 2021.07.29 |
[React] 화살표 함수에 대한 고찰 (0) | 2021.07.28 |
[정규표현식] .*? 패턴의 의미 (0) | 2021.07.23 |
댓글