[JS] JavaScript 함수형 프로그래밍 1
JavaScript에서 함수형 프로그래밍 기본
![[JS] JavaScript 함수형 프로그래밍 1](/image/functional.png)
리스트에서 홀수를 length 만큼 뽑아서 제곱한 후 모두 더한 결과값을 출력하는 코드를 작성한다고 가정해보자.
/* 명령형 코드 */
const log = console.log;
function f(list, length) {
let i = 0;
let acc = 0;
for (const a of list) {
if (a % 2) {
acc = acc + a * a;
if (++i == length) break;
}
}
log(acc);
}
function main() {
// f([1, 2, 3, 4, 5], 1);
f([1, 2, 3, 4, 5], 2);
// f([1, 2, 3, 4, 5], 3);
}
main(); // 10
여기서 명령형 코드, 명령형 프로그래밍은 무엇인가? 항상 비교되는 선언형 프로그래밍도 있다. 함수형 프로그래밍을 알아보기 전에 두개를 먼저 알아보고 넘어가자.
명령형 프로그래밍이란 프로그램의 상태와 상태를 변경시키는 구문의 관점에서 연산을 설명하는 프로그래밍 패러다임의 일종이다. 쉽게 말해, 컴퓨터가 수행할 명령들을 순서대로 써 놓은 것이라 볼 수 있다. 명령형 프로그래밍은 “How to solve it” 결과를 도출하기위해 어떻게 할지에 중점을 둔다. 선언형 프로그래밍도 일종의 패러다임이다. 선언형 프로그래밍은 반대로 “What to do for it” 무엇을 할지에 중점을 둔다.
위 코드는 명령형 프로그래밍이다. 보다시피 제곱값을 어떻게 구하는지 절차를 알 수 있다. 즉, 명령형 프로그래밍은 알고리즘을 명시하고 있다는 특징이 있다.
자, 그럼 함수형 프로그래밍은 무엇일까? 함수형 프로그래밍은 선언형 프로그래밍과 관련이있다. 명령형 코드를 선언적으로 기술하는 방식이 함수형 프로그래밍이라고 한다. 그럼 위 코드를 선언형 코드로 바꾸어 함수형 프로그래밍을 해보자.
cf) Naver D2 강연에서 함수형 프로그래밍의 이해를 돕기위해 강연자분께서 라이브 코딩을 하시는데 generator와 iterable이 나온다. 간단히 설명하자면 generator 함수를 호출하면 일반 함수와 달리 코드가 실행되지 않고 대신 실행을 처리하는 generator 객체를 반환한다.(객체안에 next(), return(), throw() 등 있음) iterable은 자바스크립트에서 순회가 가능한 값을 보통 칭한다. 더 자세하게는 여기서 설명하지 않겠다.
/* 함수형 프로그래밍 */
const log = console.log;
// 조건에 따라 반환하는 함수
function *filter(f, iter) {
for (const a of iter) {
if (f(a)) yield a;
}
}
// 맵핑하는 함수
function *map(f, iter) {
for (const a of iter) {
yield f(a);
}
}
// length만큼 리턴하는 함수
function take(length, iter) {
let res = [];
for (const a of iter) {
res.push(a);
if (res.length == length) return res;
}
return res;
}
// 결과를 누적하는 함수
function reduce(f, acc, iter) {
for (const a of iter) {
acc = f(acc, a);
}
return acc;
}
const add = (a, b) => a + b;
const f = (list, length) =>
reduce(add, 0,
take(length,
map(a => a * a,
filter(a => a % 2, list))));
function main() {
log(f([1, 2, 3, 4, 5], 1)); // 1
log(f([1, 2, 3, 4, 5], 2)); // 3
log(f([1, 2, 3, 4, 5], 3)); // 5
}
main();
위 코드에서 함수 f가 굉장히 직관적으로 바꼈다. 함수 f는 리스트 중 홀수인 원소들만 filter하고 제곱으로 map해서 length만큼 take해 reduce하는 함수다. 여기서 선언형 프로그래밍의 특징을 알 수 있다. 선언형 프로그래밍은 목표를 명시하고 알고리즘을 명시하지 않는다. 또, 굉장히 직관적이기 때문에 코드 가독성이 좋다는 장점이 있다.
위 코드는 함수형 프로그래밍의 특징에 대해서도 알 수 있다. 함수형 프로그래밍은 명령형 코드를 선언형 코드로 변경하며 로직을 추상화 시킨다고 볼 수 있다. 또, 함수가 외부에 영향을 끼치는 방식이 아닌 최대한 인자와 return값으로 소통하고 있는 것을 볼 수 있다. 함수형 프로그래밍은 외부에 영향을 끼치는 것은 외부에서 하도록 권장한다고한다. 그래서 함수 f에 return을 주었고 main 함수에서 log를 사용했다.
함수형 프로그래밍이라는 개념은 큰 개념이다. 여기서 서술한 것은 아주 기본적이며 극히 일부분이다. 추후에 D2강연을 더 보며 정리할 것이다. 강연을 좀 보다가 정리하여 포스팅하고 싶어서 다 보진 못했다. 근데 진짜 함수형 프로그래밍의 간결함에서 오는 아름다움을 느낄 수 있는 내용들이 많았다.. 여튼 갑자기 함수형 프로그래밍에 관심을 갖게된 이유는 우테코를 하면서 자바스크립트를 공부하는데 자바스크립트는 멀티 패러다임 랭귀지라고 한다. 함수형과 객체지향이 혼종의 형태로 있는 언어인 것이다.. 둘 다 알아야된다고 생각하지만 React Hooks가 도입되면서 함수형 컴포넌트 시대가 왔기 때문에 함수형 프로그래밍에 관심이 쏠리게 되었다. 또, 가독성 좋게 코드를 짜려다보니 함수형 프로그래밍에 대해 알고싶었다. 처음엔 개념들이 와닿지가 않았는데 코드를 바꿔보면서 이해하려하니 확 와닿았다. 결론은 강연자분이 짱이시다!
Reference
- Naver D2 함수형 프로그래밍과 ES6+(https://www.youtube.com/watch?v=4sO0aWTd3yc&t=1s)