커링이란?
커링이란 f(a, b, c) 를 f(a)(b)(c) 와 같이 여러 개의 인수를 단일 프로세스로, 호출 가능한 함수를 다중 프로세스 형태로 변환할 수 있도록 하는 기술이다.
보통 자바스크립트에서 커링되어진 함수는 평소처럼 호출도 하고 만약에 인수들이 충분하지 않을 때는 partial 을 반환한다.
커링은 partial 을 쉽게 적용할 수 있도록 해준다.
커링을 사용하는 이유?
커링 함수를 사용하는 이유는 함수가 여러 개의 인자를 받을 때 특정 인자를 고정할 수 있습니다. 그로 인해 함수의 재사용성을 높일 수 있습니다.
// 커링을 사용한 함수
const currying = a => b => c => a * b * c;
console.log(currying(1)(2)(3)); // 6
// 인수 고정으로 재사용성 높이기
const alwaysMultiple2 = currying(1)(2);
console.log(alwaysMultiple2(3)); // 6
커링 구현
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function pass(...args2) {
return curried.apply(this, args.concat(args2));
}
}
}
}
curry(func) 의 반환값은 curried 라는 래퍼이다. curried 라는 래퍼 안에는 두 개의 if 분기점이 있다.
if 조건을 충족하는 경우 즉 args 를 카운트한 갯수가 전달된 원래 함수 func 의 매개변수 개수와 같거나 크다면, 그대로 func 호출에 args 를 전달한다.
반면 if 조건을 충족하지 못하는 경우 아직 func 이 호출되지 않고 pass 라는 래퍼가 대신 반환된다. pass 래퍼함수가 curried 래퍼를 이전에 입력된 인수와 새로운 인수와 함께 다시 적용한다. 그 다음 새로운 curried 래퍼 호출에 인수가 충분하지 않으면 새로운 pass 래퍼를 반환하거나 최종적으로 func 결과를 반환한다.
커링 사용 예시 1)
function sum(a, b, c) {
return a + b + c;
}
const curriedSum = curry(sum);
console.log(curriedSum(1, 2, 3)); // 6, 평소처럼 단일 callable 형식으로 호출
console.log(curriedSum(1)(2, 3)); // 6, 첫 번째 인수 커링
console.log(curriedSum(1)(2)(3)); // 6, 모두 커링
sum 함수는 인수가 세 개이므로 sum.length = 3 이다.
curriedSum(1)(2)(3) 이 호출되는 과정은 다음과 같다.
1. 첫번째 curriedSum(1) 을 호출할 때 1을 렉시컬 환경에 기억하고 curriedSum(1)이 pass 래퍼를 반환한다.
2. pass 래퍼가 (2)와 함께 호출된다. 이전의 인수인 (1)과 (2)를 연결해 curried(1, 2) 를 함께 호출한다. 인수의 개수는 2개로 아직 3보다 작기 때문에 curried 는 pass 래퍼를 반환한다.
3. pass 래퍼가 다시 (3)과 함께 호출된다. 다음 호출인 pass(3) 이 이전의 인수들인 (1, 2) 를 가져와 (3) 을 연결해 curried(1, 2, 3) 호출을 한다.
4. 인수의 개수는 3개로 sum 함수의 인수 3개와 같기 때문에 if 조건을 충족해 인수를 func 에 전달해 func(1, 2, 3) 호출한 후 최종적으로 결과값을 반환한다.
커링 사용 예시 2)
function log(logMessage = console.log, date, importance, text) {
logMessage(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${text}`);
}
const curriedLog = curry(log);
// curriedLogByConsole 은 log의 첫 번째 인수가 고정된 partial 이 된다.
const curriedLogByConsole = curriedLog(console.log);
// logNow 는 log의 첫 번째 인수, 두 번째 인수가 고정된 partial 이 된다.
const logNow = curriedLogByConsole(new Date());
// infoNow 는 log의 첫 번째 인수, 두 번째 인수, 세 번째 인수가 고정된 partial 이 된다.
const infoNow = logNow("INFO");
logNow("ERROR", "에러 발생"); // [HH:mm] ERROR 에러 발생
infoNow("메세지"); // [HH:mm] INFO 메세지
출처
https://ko.javascript.info/currying-partials
https://my-first-programming.tistory.com/entry/%EC%BB%A4%EB%A7%81-Currying-%EC%9D%B4%EB%9E%80
'프로그래밍 언어 > JavaScript' 카테고리의 다른 글
[JavaScript] iterable 객체 (0) | 2023.01.11 |
---|---|
[JavaScript] 예시를 통해 알아보는 this (0) | 2022.12.28 |
[JavaScript] 문자열 자르기 (substr, substring, slice) (0) | 2022.12.05 |
JavaScript 의 동작방식 (0) | 2022.11.12 |
[JavaScript] 반복문 (0) | 2022.11.05 |