함수형 프로그래밍을 위한 함수와 함께 사용할 수 있는 고급기술이라 할 수 있다.
일반 함수(인자를 여러개 가지고 있는)처럼 단일 호출로 처리하는 함수를 각각의 인수가 호출 가능한 프로세스로 호출된 후 병합되도록 변환하는 것
💡 커링은 함수를 호출하지 않고 변환하기만 한다.
장점은 아래와 같다.
사이드 이펙트를 최대한 줄임
동일한 입력=동일한 출력이라는 순수 함수를 만족
함수의 재사용성 높음
currying은 클로저 개념을 가지고 있다.
일반 함수
// 사용할 함수 작성
const sum = (a,b) => a+b;
const multy = (a,b) => a*b;
function printCurry(fn){
console.log(arguments) // fn
return function(a){
console.log(arguments, fn) // a, fn
return function(b){
console.log(arguments, a) // b, a
return fn(a,b)
}
}
}
printCurry(sum)(1)(2) // 3
printCurry(multy)(2)(3) // 6
화살표 함수
// 사용할 함수 작성
const sum = (a,b) => a+b;
const multy = (a,b) => a*b;
const printCurry = fn => a => b => fn(a,b)
printCurry(sum)(1)(2) // 3
printCurry(multy)(2)(3) // 6
class 와 비슷하다.
인자를 주면 렉시컬 스코프에 저장이 되며 이후에 사용할 함수에 고정 값으로 둘 수 있다.
커링을 이용한 값 고정
const sum = a => b => a+b;
const sumWithOne = sum(1);
sumWithOne(3) // 4
클래스를 이용한 값 고정
class MathClass{
constructor(a) {
this.a = a
}
sum(b){
return this.a + b
}
multy(b){
return this.a*b
}
}
const sumWithOne = new MathClass(1)
sumWithOne.sum(3) // 4
예제로 본 커링은 인자의 수를 정해 놓고 사용한다.
재사용성이 좋은 것도 알고 순수 함수를 지양할 수 있어 함수형 프로그래밍에서 많이 사용한다.
하지만 만약 인자의 개수가 적은 것은 괜찮지만 많다면 오류를 뱉고 argument는 각 함수 안의 인자들만 반환한다.
함수를 확장하고 싶다면 어떻게 해야할까
아래와 같은 상황을 가정해본다.
ex)
함수 하나로 커링을 구현하는데 인자들의 수는 랜덤이며 그 수들의 합을 구해야한다.
=> 내가 구현한 클로저 함수가 3갠데 5개가 들어올 수도 2개가 들어올 수도 있다.
function sum(num) {
let result = num
return function adder(nextNum) {
// 마지막으로 함수 반환 값을 내기 위한 ()
if (nextNum === undefined) {
return result;
}
// () 전까진 result의 값을 계속 더하고 함수를 다시 실행한다.
result += nextNum;
return adder;
}
}
sum(1)(2)() // 3
sum(2)(10)(2)(12)() // 26
렉시컬 환경과 재귀를 이용해 해결할 수 있다.
Process
렉시컬 환경에서 결과를 반환하는 변수 선언
반환하는 함수 선언
만약 매개변수가 없다면 렉시컬 환경에 있는 결과값을 반환한다.
만약 매개변수가 존재한다면 결과값에 매개변수를 더하고 다시 자기 자신을 반환한다(재귀).
논커리 : 일반 함수에서 사용하는 단일 호출
=> 매개변수가 부족해도 함수 실행 가능
커리 : 인자들을 모아 프로세스로 호출 후 병합
=> 매개변수를 다 받을 때까지 실행 보류