저번 시간에 구현한 함수를 응용해서 사용할 수 있는 함수 go, pipe, curry를 구현하고 사용법을 알아보겠습니다.
전달 인자로 받은 함수를 차례대로 실행시키는 함수입니다. reduce 함수를 이용해서 구현합니다.
// go 함수 구현
const reduce = (f, acc, iter) => {
if (!iter) {
iter = acc[Symbol.iterator]()
acc = iter.next().value
}
for (const a of iter) {
acc = f(acc, a)
}
return acc
}
const go = (...args) => reduce((a, f) => f(a), args)
// go 함수 사용
go(
0,
(a) => a + 1,
(a) => a + 10,
(a) => a + 100,
console.log
) // 111
const result = go(
0,
(a) => a + 1,
(a) => a + 10,
(a) => a + 100
)
console.log(result) // 111
함수를 합성하는 함수입니다. go 함수를 이용해서 구현합니다.
[예제 1] go 함수 코드
const result = go(
0,
(a) => a + 1,
(a) => a + 10,
(a) => a + 100
)
console.log(result) // 111
위 코드에서 pipe 함수를 구현해서 사용해보겠습니다.
[예제 2] pipe 함수 코드
const pipe = (...fs) => (a) => go(a, ...fs)
const f = pipe(
(a) => a + 1,
(a) => a + 10,
(a) => a + 100
)
console.log(f(0)) // 111
pipe 함수는 인자로 받은 함수를 합성합니다. go 함수를 대체할 수 있고 pipe 함수 결과값으로 인자를 받을 수 있습니다.
[예제 3] 인자 2개를 못받는 기존 pipe 결과함수
const add = (a, b) => a + b
go(
add(0, 1),
(a) => a + 10,
(a) => a + 100,
console.log
) // 111
const f = pipe(
add,
(a) => a + 10,
(a) => a + 100
)
console.log(f(2, 7)) // NaN
인자를 2개로 받는 함수는 지금의 pipe 함수로 정상적으로 실행하지 못합니다. pipe 함수를 보강해보겠습니다.
[예제 4] 인자 2개를 받을 수 있는 pipe 결과함수
const pipe = (f, ...fs) => (...as) => go(f(...as), ...fs)
const add = (a, b) => a + b
const f = pipe(
add,
(a) => a + 10,
(a) => a + 100
)
console.log(f(2, 7)) // 119
const f2 = pipe(
(a) => a + 1,
(a) => a + 10,
(a) => a + 100
)
console.log(f2(9)) // 120
인자를 2개를 받을 수 있고 인자 1개도 문제 없이 받습니다.
커링(curring)하는 함수입니다. 커링은 f(a, b, c)
처럼 단일 호출로 처리하는 함수를 f(a)(b)(c)
와 같이 각각의 인수가 호출 가능한 프로세스로 호출된 후 병합되도록 변환하는 것입니다.
const curry = f =>
(a, ..._) => _.length ? f(a, ..._) : (..._) => f(a, ..._)
const mult = curry((a, b) => a * b)
console.log(mult(3)) // (..._) => f(a, ..._)
console.log(mult(3, 2)) // 6
console.log(mult(3)(2)) // 6
이 curry 함수는 전달 인자 2개까지 커링할 수 있습니다.