실습 방법
크롬에서 F12를 누르시고 코드를 복붙해서 가지고 놀면 됩니다. 원래는 typescript로 되어 있지만 바로바로 확인가능하게 하기 위해 javascript로 재작성하여 글을 쓰고 있습니다.
함수의 합성은 무엇인가?
f: X->Y, g: Y->Z 일 때 g∘f: X -> Z 를 합성함수라고 정의한다. 합성함수는 결합법칙을 만족하고 교환법칙을 만족하지 않습니다. 또한 f의 공역과 g의 정의역이 같아야 합니다.
위 정의 그대로 코드로 작성해보자
const compose = (...fns) => (...args) => fns.reduceRight((rest, fn) => [fn.call(null, ...rest)], args)[0]
코드를 쉽게 풀어 써보면 f, g, h를 파라미터로 받았을 때 리턴되는 함수의 동작 흐름은 아래와 같습니다.
h -> argument 넣고 실행 -> 그 결과를 배열로 다음 reduceRight 연산에 전달 -> g -> h의 실행 결과를 인자로 실행 -> 그 결과를 다음 reduceRight 연산에 전달 -> h 실행 -> h의 실행 결과를 인자로 실행 -> 그 결과를 다음 reduceRight 연산에 전달 -> reduceRight 끝 -> 그 값의 0번째 리턴입니다.
이를 수학적으로 표현 한다면 h(g(f(값))) 이다. 함수의 합성이 된 것이지요
예제
const composedFunction = compose((b) => b * b, (a) => a + 1) // 함수를 리턴합니다.
composedFunction(1) // (1 + 1) * (1 + 1) = 4
수학적으론 맞는데 쓰기 불편합니다.
위의 compose는 h(g(f(값))) 을 만들고 싶으면 f, g, h 순서대로 파라미터를 작성해야 합니다. 이 점이 사용하기에 직관적이지 않기 때문에 h, g, f 를 넣어도 h(g(f(값))) 이 되게끔 작성해보겠습니다.
const pipe = (...fns) => (...args) => fns.reduce((rest, fn) => [fn.call(null, ...rest)], args)[0]
예제
const pipeFunction = pipe((a) => a + 1, (b) => b * b);
pipeFunction(1) // 4
커링이란 것도 있습니다.
커링은 다중 인수를 갖는 함수를 단일 인수를 갖는 함수열로 바꾸는 것을 말합니다. 말이 참 어렵죠 코드로 보면 이해가 쉽습니다.
// 원본 함수
const func = (a, b)=>{ ... }
// 원본 함수를 커링
function(a){
return function(b){
return func(a, b);
}
}
원본 함수는 실행시 모든 파라미터를 다 입력해야 하지만 커링된 함수는 시점은 상관 없이 맞는 개수의 파라미터가 들어왔을 때 실행 됩니다. 우리는 파라미터를 항상 2개만 받지 않죠 몇개의 파라미터던 커링 되는 함수를 구현해보도록 하겠습니다.
const curry = (fn, length = fn.length) => {
return (...args) => {
return args.length >= length
? fn(...args)
: curry((...nextArgs) => fn(...args, ...nextArgs), fn.length - args.length);
}
}
const curryied = curry((a, b, c) => console.log(a, b, c))
curryied(1)(2, 3) // 1, 2, 3
curryied(1)(2)(3) // 1, 2, 3
curryied(1, 2)(3) // 1, 2, 3
이 됩니다. 코드는 파라미터가 다 올때까지 파라미터를 차곡차곡 쌓아 커링을 하는게 전부 입니다.
(이 글은 제 과거 블로그 글을 다시 정리하여 쓴 글입니다. 지식이 일천하여 틀린곳이 있을 수 있습니다.)
'프로그래밍' 카테고리의 다른 글
#4 부수효과 (0) | 2022.04.08 |
---|---|
#3 maybe 모나드와 either 모나드 (0) | 2022.04.08 |
#1 함수형 프로그래밍에서 모나드는 무엇인가? (0) | 2022.04.07 |
CSS 적용 우선순위 (0) | 2022.04.06 |
typescript - enum 값에 따라 함수 타입 설정하기 (0) | 2022.04.05 |