Compose
함수형 프로그래밍의 이점
함수형 프로그래밍은 SW 개발에서 사용되는 패러다임 중 하나이다. 물론 모든 상황에 적합한 것은 아니며, 사용 사례와 요구 사항에 따라 고려해봐야함.
-
높은 수준의 추상화: 함수형 프로그래밍은 데이터와 함수를 조합해서 추상화를 달성한다. 이를 통해 코드가 더 간결해지고, 이해하기 쉬워진다.
-
불변성: 함수형 프로그래밍은 데이터를 변경하지 않고, 새로운 값을 생성한다. 이로 인해 코드가 예측 가능하고 디버깅이 쉬워진다.
-
함수의 순수성: 순수 함수는 동일한 입력에 대해 항상 동일한 결과를 반환하며, 부작용이 없다. 이로 인해 코드가 더 안정적이고 테스트하기 쉬워진다.
-
모듈성: 함수형 프로그래밍은 작은, 재사용 가능한 함수를 조합하여 프로그래밍을 구축한다.
-
병렬 처리: 함수형 프로그래밍은 부작용 없는 순수 함수를 사용하기 때문에 병렬처리를 쉽게 구현
-
지연 평가: 함수형 프로그래밍은 필요한 경우에만 계산을 수행한다. 이를 통해 불필요한 연산을 줄이고, 메모리 사용량을 최적화할 수 있다.
예시 코드
예를 들어, 과일의 가격을 알려주는 함수와 비싼지 아닌지 여부를 알려주는 함수가 있을때 일반 프로그래밍에선 두 함수를 아래와 같은 방식으로 조합할 것이다.
export function getPrice(name: string): number | undefined {
if( name === "tomato"){
return 7000;
} else if (name === "orange"){
return 15000;
} else if (name === "apple"){
return 10000;
}
}
export const isExpensive = (price: number | undefined) =>{
if(price === undefined) return false;
return price > 10000;
}
export const isExpensivePrice(name:string):boolean =>{
return isExpensive(getPrice(name));
}
그렇지만, 위의 방식대로 함수를 조합한다면, 재사용성이 떨어지는 문제가 있다. 함수를 조합하는 방향에 따라서 새로운 불필요한 조합용 함수를 생성해야한다.
그래서 아래와 같이 Generic을 이용하여 compose 함수를 구현 가능하다.
export const compose = <A,B,C>(g:(y:B) => C, f:(s:A)=> B) => (x:A) => {
return g(f(x));
}
// <A,B,C>((B) => C, (A)=> B) => (A) => C
export const main = () => {
const res = compose(isExpensive,getPrice);
console.log(res("orange"));
}
main(); // true
위의 compose 함수의 경우 f로 명시된 함수가 먼저 수행된 후, g가 수행된다. 그리고 가장 밖에 있는 매개 변수 (x:A)가 가장 먼저 매개변수가 입력되는 부분으로 볼 수 있다.
compose 함수로 조합되는 res 함수는 위에 정의한 isExpensivePrice와 같다.
function compose<string,number,boolean>( g: (y: number) => boolean, f: (s: string) => number): (x: string) => boolean
res 함수로 리턴되는 타입은 아래와 같다.
const res: (x: string) => boolean
Generic이 헷깔리면 :type을 지우고, 보거나 webstorm에서 마우스를 올리면 어떤 형식으로 함수가 선언되는지 볼 수 있다. 대게의 경우, 타입이 틀리면 컴파일러에서 잡아주니 이것을 참고하면 된다.