Currying
- Currying은 여러 개의 인자를 가진 함수를 호출 할 경우, 파라미터의 수보다 적은 수의 파라미터를 인자로 받으면 누락된 파라미터를 인자로 받는 기법을 말한다. HAskell , Scala와 같이 전통적인 함수형 언어에는 기본내장이 되어있지만, JS에서는 커링이 내장되어 있지 않습니다.
왜 필요한가요 ?
함수안에 함수를 쓰는건 "함수형 프로그래밍"에서는 아주 흔한 광경이고, 그렇게 쓰다보면,
함수(함수(함수(함수(함수.....)와 같은 무한액자식 구성이 될 수 있고, 이렇게 되면, 가독성과 에러잡는데 엄청난 문제가 생기게 된다. 그리고, 사용하기도 어려워진다.
Code(구현)
- Currying의 간단한 예제부터 보자.
- Currying은 함수가 재귀적으로(Nested)한 형태를 띄고 있을 때, 그걸 풀어해치기 위해 나온 개념이므로, 함수를 리턴하게 디자인된 패턴이다.
- 이때, 받은 인자가 2개이상이면, 그 즉시, 그 함수를 실행하고, 아니라면, 인자를 또 받는 함수를 리턴한다.
- 따라서, 아래와 같은 코드로 작성이 가능하게 된다.
const curry = f =>
(a,..._) => _.length ? f(a,..._)
:(..._) =>f(a,..._);
const mult = curry((a,b) => a*b);
const mult3 = mult(3);
console.log(mult3(10)) // 3*10 =30
console.log(mult3(5)) // 3*5 = 15
Currying을 적용시킨 함수들과 Go가 합쳐지면, 엄청난 시너지 효과를 내게 되는데, 짝수를 뽑아내는 로직을 Go와 Currying의 개념을 이용해서 작성해보자!
Map,Reduce,Filter,Go,Curry의 로직은 아래와 같이 구현되어있다고 하자.
const curry = f => (a,..._) => _.length ? f(a,..._)
:(..._)=> f(a,..._);
//map
const map = curry((f,iter) =>{
let res=[];
for (const a of iter){
res.push(f(a));
}
return res;
});
//Filter
const filter = curry((f,iter) =>{
let res=[];
for (const a of iter){
if (f(a)) res.push(a);
}
return res;
})
//reduce
const reduce = curry((f,acc,iter) =>{
if(!iter){
iter=acc[Symbol.iterator]();
acc=iter.next().value;
}
for (const a of iter){
acc=f(acc,a);
}
return acc;
})
//go
const go = (...args) => reduce((a,f)=>f(a),args);
const arr=[1,2,3,4,5,6,7]
아래와 같이, 나열을 하면, 짝수를 뽑아내는 로직이 만들어진다.
go(
arr,
filter(n=>n%2===0),
map(n=>n)
console.log
)
만약, Currying이 적용되지 않은 Map,Reduce ,Filter을 이용했다면, 어떻게 될까?아래와 같이, 함수를 직접 Function 형태로 넘겨줘야할 것이다.
go(
arr,
num=>filter(n=>n%2===0,num),
num=>map(n=>n,num),
);
왜 이런 차이가 발생할까?
Filter속성에, Currying이 적용이 되어, Reduce가 실행되는 과정(정확히는 , (a,f) => f(a) 과정 )에서 Filter가 다음 함수의 호출을 기다리기 때문이다. 마찬가지로, map 또한 Currying이므로, 뒤에서 또 다른 함수호출을 기다리게 되고, 이와같이 계속 꼬리에 꼬리를 무는 형식으로 한가지의 데이터에 대해서, 로직을 적용시킬 수 있게 된다.
See the Pen JS_currying by Doge (@DogeIsFree) on CodePen.
Ref
위 글은 유인동님의 함수형 프로그래밍과 JavaScript ES6+를 보고 작성한 글입니다.
https://www.inflearn.com/course/functional-es6/dashboard
'Web Front-end > 함수형 프로그래밍(FP)' 카테고리의 다른 글
[JS/함수형] 추상화 연습해보기 (0) | 2022.05.31 |
---|---|
[JS/함수형] Go, Pipe (0) | 2022.05.27 |
[JS/함수형] Reduce (0) | 2022.05.25 |
[JS/함수형] Map,Filter 구현 (0) | 2022.05.25 |
[JS/함수형] 제너레이터와 이터레이터 (0) | 2022.05.22 |