커링(Currying)은 인수 여러 개를 받는 함수 f(a, b, c)를 인수 하나씩 받는 함수의 사슬 f(a)(b)(c)로 바꾸는 기법이다. 바꾸기만 하고 원래 함수를 호출하지는 않는다. 이름은 해스컬 커리(Haskell Curry)에서 왔다.
const add3 = (a, b, c) => a + b + c
const curried = (a) => (b) => (c) => add3(a, b, c)
curried(1)(2)(3) // 6
const add1 = curried(1) // b와 c를 차례로 기다리는 함수
add1(2)(3) // 6앞쪽 인수만 넘겨 둔 함수에 이름을 붙여 재사용할 수 있다. 예를 들어 log(date)(level)(message) 모양이면 log(new Date())로 "지금 시각 로그" 함수를 만들어 둔다. 인수 하나짜리 함수가 되면 함수 합성의 pipe·compose에 끼우기도 쉽다.
부분 적용(Partial Application)과 다른 점
부분 적용은 인수 일부를 미리 고정해 나머지 인수를 받는 새 함수를 만드는 것이다. 둘은 자주 섞여 쓰이지만, 부분 적용된 함수는 나머지 인수를 받으면 바로 결과를 돌려준다. 커링된 함수는 인수를 다 받을 때까지 사슬의 다음 함수를 돌려준다. 이 차이는 인수가 셋 이상일 때 드러난다.
const addOne = add3.bind(null, 1) // 부분 적용: 첫 인수를 1로 고정
addOne(2, 3) // 6, 바로 결과
curried(1)(2) // 아직 함수: c를 기다린다- 자바스크립트에서는
Function.prototype.bind로 부분 적용을 할 수 있다. 첫 인수는this이고, 그 뒤에 넘긴 값이 앞쪽 인수로 고정된다 - lodash의
_.curry같은 실용 구현은f(1, 2)처럼 한꺼번에 불러도,f(1)(2)처럼 하나씩 불러도 되는 래퍼를 돌려준다. 인수를 하나씩만 받는 엄밀한 커링보다 너그러운 형태다 - 커링된 함수는 앞서 받은 인수를 클로저(Closure)로 기억해 둔다. 함수를 값으로 넘기는 패턴은 콜백과도 이어진다
출처: Wikipedia - Currying · Contrast with partial function application · javascript.info - Currying · MDN - Function.prototype.bind: Partially applied functions