— 개발상식
함수형 프로그래밍은 하나의 프로그래밍 패러다임으로 정의되는 일련의 코딩 접근 방식이며, 자료처리를 수학적 함수의 계산으로 취급하고 상태와 가변 데이터를 멀리하는 프로그래밍 패러다임을 의미한다.
함수형 프로그래밍 언어로 설계된 클로저,스칼라,하스켈
등의 언어가 있고, 자바스크립트,코틀린,파이썬
등에도 최근 버전에 함수형 프로그래밍 문법이 추가 되었다.
잠시 당신이 나무꾼이라고 가정해보자. 당신은 숲에서 가장 좋은 도끼를 가지고 있고, 그래서 가장 일 잘하는 나무꾼이다. 그런데 어느 날 누가 나타나서 나무를 자르는 새로운 패러다임인 전기톱을 알리고 다닌다. 이 사람이 무척 설득력이 있어서 당신은 사용하는 방법도 모르면서 전기톱을 사게 된다. 당신은 여태껏 했던 방식대로 시동을 걸지도 않고 전기톱으로 나무를 마구 두들겨댄다. 곧 당신은 이 새로운 전기톱은 일시적인 유행일 뿐이라고 단정하고 다시 도끼를 쓰기 시작한다. 그때 누군가 나타나서 전기톱의 시동 거는 법을 가르쳐 준다.
— 닐포드 , “함수형 사고”
함수형 프로그래밍은 기존 절차적 프로그래밍과 객체 지향형 프로그래밍과는 다른 새로운 방식이다. 함수형 프로그래밍을 배우는 것은 스칼라나 클로저에 관심이 없고 앞으로 쓰지 않을 것 같다고 해도 다른 방식으로 사고하는 법을 배우는 것이다.
새로운 계산방법을 배우는 것 처럼 사고의 전환을 필요로 하며 다양한 사고방식으로 프로그래밍을 바라보면 유연한 문제해결이 가능하다.
1let num = 1;2
3function add(a) {4 return a + num;5}
위와 같은 예제에서는 add
라는 함수 안에서 전역으로 선언된 변수인 num
을 참조하기 때문에 순수함수라고 볼 수 없다.
1// 순수함수2function add(a, b) {3 return a + b;4}5
6const result = add(2, 3);
위와 같이 add
의 함수가 프로그램 실행에 영향을 미치지 않고 입력 값에 대해서만 값의 변환이 있으므로 순수함수이다.
순수 함수는 프로그램의 변화 없이 입력 값에 대한 결과를 예상 할 수 있어 테스트가 용이하다.
1let person = { name: "jongmin", age: "26" };2
3function increaseAge(person) {4 person.age = person.age + 1;5 return person;6}
위의 예제에서는 increaseAge
함수에서 전역으로 선언된 person
의 age
속성을 변경하므로 불변성 유지를 만족하지 못한다.
1// 비상태, 불변성 만족2const person = { name: "jongmin", age: "26" };3
4function increaseAge(person) {5 return { ...person, age: person.age + 1 };6}
위처럼 객체의 값을 바꾸기 위해서는 데이터의 복사본을 만들어, 그 복사본을 사용해 작업을 진행하고 반환한다.
명령형 프로그래밍은 무엇을 어떻게 할 것인가에 주목하고, 선언헌 프로그래밍은 무엇을 할 것인가에 주목한다.
1let numbers = [1, 2, 3];2
3function multiply(numbers, multiplier) {4 for (let i = 0; i < numbers.length; i++) {5 numbers[i] = numbes[i] * multiplier;6 }7}
위의 예시에서는 for문을 사용해서 배열의 각 요소에 multiplier 곱해주는 명령형 프로그래밍이다.
함수형 프로그래밍에서는 마찬가지로 if,switch,for
등 명령문을 사용하지 않고 함수형 코드로 사용해야한다.
1// 선언형 프로그래밍2function multiply(number, multiplier) {3 return number.map((num) => num * multiplier);4}
위의 예시는 for
문을 map
으로 대치했고, Javascript 에서는 filter,map,take,reduce
등의 함수형 코드를 사용한다. 명령형에서 함수형으로 변환하는 과정은 OPEN 투게더님 블로그을 참조해도 좋을 것 같다.
함수형 프로그래밍에서는 함수가 1급 객체가 된다. 1급 객체의 특징은 다음과 같다.
1// 1급 객체2const addTwo = (num) => num + 2;3const multiplyTwo = (num) => num * 2;4const transform = (numbers) => numbers.map(addTwo).map(multiplyTwo);5
6console.log(transform([1, 2, 3, 4])); // [6, 8, 10, 12]
위의 예시에서는 함수를 변수에 할당하거나 반환하는 1급 객체로서의 특징을 보여준다.
그리고 고차 함수의 속성을 가져야 하는데, 고차 함수의 특징은 다음과 같다.
1// 고차 함수2const addInform = (name) => (age) => age + name;3const jongmin = addInform("종민");4
5console.log(jongmin("96")); // 96종민
위의 예제처럼 함수의 반환 값으로 다른 함수를 사용하거나, 함수의 반환 값으로 또 다른 함수를 사용 할 수 있어야 한다.