hyper의 플러그인 중 하나인 hyper-letters의 코드를 보던 중에 꽤 신기한 코드를 발견했다.
(오픈 소스지만 코드를 그대로 가져오기는 조금 그래서 예시로 표현했다.)
const foo = num1 => num2 => num3 => {
console.log(num1 + num2 + num3)
}
물론 예시라 해당 코드의 의미와 동작에 대해서는 본래와 아예 다르지만, 그 겉모습만 보면 낯설다. 그래도 사용하는 것으로 보아 특별한 메리트가 있을 것으로 생각해, 검색해본 결과 나와 같은 의문을 가진 사람이 물론 있었다.
답변이 매우 길지만... 맨 첫 줄에 간단하게 그냥 Curried function
이라고 쓰여 있다. 커링 함수인가 보다. JavaScript에서 커링이란 매개변수를 일부 저장해놓고 함수를 재사용할 수 있게 해주는 기법이다.
const add = function(x) {
return function(y) {
return x + y;
}
}
const add5 = add(5); // 매개변수 일부를 저장하여 재사용
console.log(add5(5)); // 10
console.log(add5(10)); // 15
console.log(add(2)(3)); // 5
이를 화살표 함수로 간단히 고치면,
const add = x => y => x + y;
const add5 = add(5); // 매개변수 일부를 저장하여 재사용
console.log(add5(5)); // 10
console.log(add5(10)); // 15
console.log(add(2)(3)); // 5
동일한 결과가 나온다. 5줄이나 차지했었는데 무려, 한 줄로 줄일 수 있다. 어떻게 동작할까?
x + y
는 화살표 함수의 동작에 따라 Return value
가 된다. 이처럼, 함수인 y => x + y
도 Return value
가 된다.
필요하다면, 더 많은 화살표를 추가할 수 있다.
const add => x => y => z => x + y + z;
인자의 개수를 계속 늘리고 싶다면 다음과 같은 패턴을 사용할 수 있다.
const $ = x => k => $(k(x));
const add = x => y => x + y;
const multiple = x => y => x * y;
$ (5) // 5
(add(10)) // + 10 = 15
(multiple(2)) // * 2 = 30
(console.log) // 30
동작 과정은... 궁금하다면 편집기에서 중단점 찍고 천천히 확인해보길...
Partial Applicatoin이라는 기법을 적용하기 위해 사용할 수 있다.
Currying과 Partial Application을 비교해 놓은 글도 있으니 참조하면 도움이 될 것이다.
쉽게 말해, 커링은 인자를 하나씩만 고정할 수 있지만, Partial Application은 여러 인자를 한 번에 고정할 수 있다.
const partial = (f, ...a) => (...b) => f(...a, ...b);
const add3 = (x, y, z) => x + y + z;
partial(add3)(1, 2, 3); // 6
partial(add3, 1)(2, 3); // 6
partial(add3, 1, 2)(3); // 6
partial(add3, 1, 2, 3)(); // 6
partial(add3, 1, 2, 3, 4, 5)(1, 2, 3, 4, 5); // 6
add3
함수는 3개 초과의 인자를 받을 수 없기 때문에 3개부터 잘리지만, 여러 개의 인자를 한꺼번에 저장할 수 있음을 알 수 있다.