[FP] - curry, pipe, go
함수형 프로그래밍은 함수들을 마치 블럭처럼 조립해 작성하는 모양을 띄곤 합니다. 다만 기본적인 JS에서 함수형 프로그래밍은 가독성이 좋지 않습니다.
함수를 인자로 넘겨주어야 하기 때문에 함수가 계속 중첩되는 모양이 되고 실행은 중첩의 중심부터 실행되기 때문에 가독성에 문제가 생깁니다.
오늘 다룰 curry,
pipe
, go
함수를 이용하면 가독성 좋은 함수형 프로그래밍 코드를 만들 수 있습니다.
어떤가요? 위에서 아래로 순차적으로 매우 쉽게 읽을 수 있지 않나요?
파이프 연산자 제안
현재 파이프 연산자는, TC39 프로세스 단계중 stage 2에 있습니다.
파이프 연산자란 연속된 함수의 조합을 가독성 있게 바꿔주는 연산자입니다.
curry,
pipe
, go
는 연속해서 실행하는 함수 조합을 쉽게 만들어 줍니다. 하나씩 알아보도록 하겠습니다.
주의
앞으로
map
,filter
,reduce
와 같은 함수들을 사용할 예정입니다. 이 글에서는 앞선 함수들의 구현체는 언급하지 않을 예정입니다.이 함수들은 함수를 첫 번째 인자로 받고, 배열을 두 번째 인자로 받는 형태로 사용할 것입니다.
예를 들어
arr.map(i=> i*2)
는map(i=>i*2 , arr)
로 사용합니다.
curry
커링은 여러 개의 인자를 가진 함수를 하나의 인자만 받고 나머지 인자를 받는 새로운 함수를 반환하는 기법입니다. 예시를 들어보겠습니다.
예시에서 add()
는 두 개의 인자를 받아 더한 값을 반환합니다. 반면, curriedAdd()
는 첫 번째 인자 a
를 받고, 그 후에 클로저를 통해 두 번째 인자 b
를 받아 a + b
를 계산하는 새로운 함수를 반환합니다. 이렇게 하면 curriedAdd()
를 호출한 뒤 반환된 함수에 다음 피연산자를 전달하여 결과를 얻을 수 있습니다.
curry()
는 여러 개의 인자를 가진 함수를 단일인자를 받아 나머지 인자를 받는 새로운 함수를 반환하는 curring 함수로 변경하는 헬퍼함수입니다.
Typescript에서의
curring
,pipe
,go
우리는 각각의 헬퍼함수를 사용하면서 타입 추론을 기대합니다. 하지만 타입스크립트의 특성상 각각의 헬퍼함수를 구현하면서 타입 추론을 위해서는 오버로딩을 통해 타입을 구현해야합니다. 이 글에서는 해당 오버로딩에 대한 코드를 생략합니다.
선언한 curry함수를 사용하면 쉽게 curring을 구현할 수 있습니다.
go
go
함수는 함수를 인자로 받아서 순차적으로 즉시 실행
하게 도와주는 헬퍼 함수입니다.
go()
의 인자는 함수들을 받습니다. go()
에 전달된 함수들은 이전 함수의 반환값이 다음 함수의 인자가 됩니다.
첫번째 ()=> 1
의 반환값인 1이 다음 함수인 i=> i+ 10
의 인자로 넘겨집니다. 타입스크립트를 사용하면 오버로딩을 통해 타입추론이 가능합니다.
이때 curry()
와 함께 사용하면 매우 간결하고 가독성 좋은 프로그래밍이 가능해집니다.
JS 콜백함수의 축약형태
콜백 함수의 시그니처가 사용처인 함수에서 요구하는 형식과 일치할때, 호출문을 생략할 수 있는 JS의 특성입니다.
예를 들어,
arr.forEach(console.log)
은arr
배열의 각 요소를console.log
함수에 전달하여 출력하는 동작을 수행합니다. 이 경우에는console.log
함수가forEach
함수에서 요구하는 콜백 함수의 형식과 일치하기 때문에 별도로 함수 선언이나 화살표 함수를 사용하지 않고도 간결하게 사용할 수 있는 것입니다.
pipe
pipe()
는 여러 함수를 차례대로 합쳐서 하나의 함수를 반환합니다. go()
와 다르게 즉시 실행하지 않습니다.
지금까지 알아본 헬퍼함수를 이용하면 보다 가독성 좋은 함수형 프로그래밍을 만들 수 있습니다.