커링이란 여러 파라미터를 가지는 함수를 단일 파라미터를 갖는 함수들의 연속으로 변경하는 것을 의미합니다.
// 1. 커링
// 1. 2개의 파라미터를 받아 합을 계산하는 함수에 커링 적용
const curriedSum = a => {
return b => {
return a + b
}
}
// 화살표 함수를 적용한다면 한줄로 표현이 가능합니다.
// const curriedSum = a => b => a + b
// 2. 커링이 적용된 함수 실행
const res = curriedSum(3)(4)
console.log('res', res) // 7
커링이 가능한 이유는 외부 함수의 컨텍스트가 소멸되어도 내부 함수가 외부 함수의 실행환경을 참조할 수 있는 클로져 때문입니다.
수학자 하스켈 커리에 의해 발전되어 붙여진 이름이고, 클로져가 가능한 다른 언어에서도 해당합니다.
# 1. 2개의 파라미터를 받아 합을 계산하는 함수에 커링 적용
def curried_sum(a):
def sum_a(b):
return a + b
return sum_a
# 람다를 적용한다면 한줄로 표현이 가능합니다.
# curried_sum = lambda a: lambda b: a + b
# 2. 커링이 적용된 함수 실행
res = curried_sum(3)(4)
print('res', res) # 7
함수 합성을 통해 코드 재활용성을 높일 수 있습니다.
reduce, args(유사 배열 객체) 와 섞어서 여러 함수를 받아서 실행하는 compose 함수를 만들 수 있습니다.
const compose = (...args) => {
return args.reduce((prev, next) => {
return (...values) =>{
return next(prev(...values))
}
}, k => k)
}
다음 예시처럼, 1. 버림, 2. 절대값, 3. 세제곱 3개의 함수를 합성 후
-5.54
와 [1, 2, 3, 4, 5]
리스트의 map에 적용할 수 있습니다.
// 1. 버림 함수
const trunc = x => ~~x
// 2. 절대값 함수
const abs = x => x < 0 ? x * -1 : x
// 3. 세제곱 함수
const triple = x => x * x * x
// 4. 컴포즈 함수
const compose = (...args) => {
return args.reduce((prev, next) => {
return (...values) =>{
return next(prev(...values))
}
}, k => k)
}
// 5. 함수 합성
const composed = compose(
trunc,
abs,
triple
)
// 6. 결과 확인
console.log('res', composed(-5.54)) // 125
const a = [1, 2, 3, 4, 5]
console.log(a.map(composed)) // [ 1, 8, 27, 64, 125 ]
물론 아래처럼 클로져랑 커링 1번 사용해서 할수도 있는데 compose랑 비교했을때 아래 방법은 오른쪽에서 왼쪽으로(f1~f3)을 읽어야 해서
아무래도 왼쪽 -> 오른쪽으로 읽는 compose 보다는 조금 낯설다는 점이 있습니다.
const f = (f1, f2, f3) => {
return x => f3(f2(f1(x)))
}
const fComposed = f(trunc, abs, triple)
const res = fComposed(-5.54)
console.log('res', res) // 125
함수가 바로 실행되지 않습니다. 비용이 많이드는 파라미터를 넣고 재활용해서 효율적으로 사용할 수 있습니다.
const log = a => b => c => `${a}-${b}-${c}`
const todayLog = log(new Date().getDate())
const res = todayLog('service')('error')
console.log('res', res) // 14-service-error