함수형 프로그래밍
함수형 프로그래밍
은 거의 모든 것을 순수 함수
로 나누어 문제를 해결하는 기법으로, 작은 문제를 해결하기 위한 함수를 작성하여 가독성을 높이고 유지보수를 용이하게 해 준다.
또한, 모든 것을 순수한 수학적 함수 스타일로 묶으려고 하는 프로그래밍 패러다임이다.
함수형 프로그래밍은 '어떻게 해결할 것인가'가 주안점인 명령형 스타일과 달리 '무엇을 해결할 것인가'가 주안점이다.
함수형 프로그래밍을 지원하는 언어들에는 Haskell, JavaScript, Python, Scala, Erlang, Lisp, ML 등이 있다.
함수형 프로그래밍의 특징
1. 순수 함수
int sum(int a, int b)
{
return a + b;
}
sum 함수는 두 개의 숫자만 입력받아 두 수의 합을 반환하는 순수 함수이다.
순수 함수의 특징은 아래의 두 가지가 있다.
- 순수 함수는 다른 것과 관계없이 항상 동일한 인수에 대해 동일한 출력을 생성한다.
- 순수 함수는 어떠한 인수나 로컬/글로벌 변수 또는 입/출력 스트림을 수정하지 않는다.
순수 함수는 결과가 입력 매개 변수에만 의존하며, 반환 값 외에는 외부 영향을 미치지 않는 함수이다.
sum 함수에서도 불 수 있듯이, sum의 출력 값은 항상 a와 b에 의해서 결정된다.
순수 함수는 부작용이나 숨겨진 입출력이 없기 때문에 함수형 프로그래밍을 사용한 프로그램은 디버깅하기 쉽다.
이런 측면에서 함수형 프로그래밍은 객체 메서드가 객체의 상태와 상호 작용하도록 설계된 객체지향 프로그래밍과 대조적이며,
외부 상태가 함수 내에서 종종 조작되는 절차적 스타일 코드와는 대조적이다.
int c = 10;
int sum(int a, int b)
{
return a + b + c;
}
이 예시는 sum 함수의 출력 값이 인자인 a와 b뿐만 아니라 외부에 선언된 c의 영향까지 받고 있기 때문에 순수 함수라고 할 수 없다.
2. 재귀
함수형 언어에는 "for" 또는 "while" 루프가 없다.
기능 언어의 반복은 오로지 재귀
를 통해 구현되고, 재귀 함수는 base case에 도달할 때까지 반복적으로 자신을 호출한다.
fib(n)
if (n <= 1)
return 1;
else
return fib(n - 1) + fib(n - 2);
3. 참조 투명도
함수형 프로그램에서 변수는 일단 정의되면 프로그램 전체에서 값이 변경되지 않는다.
함수형 프로그램에는 할당문이 없는데 즉, 대입문(=)이 존재하지 않는다. 만약 값을 저장해야 하는 경우에는 대신 새로운 변수를 생성한다.
따라서 어떤 변수든 실행 지점에서 실제 값으로 대체할 수 있기 때문에 부작용의 가능성이 없고 변수의 상태는 항상 일정하다.
x = x + 1 // 변수 x에 할당된 값이 변경됨
위의 코드는 대입문으로 인해 x의 값이 변경된다. 따라서 참조적으로 투명하지 않은 코드이다.
4. 고차 함수
고차 함수
란 함수가 함수를 값처럼 매개변수로 받아 로직을 생성할 수 있는 것을 말한다.
고차 함수를 쓰기 위해서는 해당 언어가 일급 객체
라는 특징을 가져야 하고, 그 특징은 아래와 같다.
- 변수나 메서드에 함수를 할당할 수 있다.
- 함수 안에 함수를 매개변수로 담을 수 있다.
- 함수가 함수를 반환할 수 있다.
// 고차 함수 예시
show_output(f) // 함수 show_output이 인수 f를 사용하여 선언
f; // 전달된 함수 호출
print_gfg // 다른 함수 선언
print("hello gfg");
show_output(print_gfg) // 다른 함수에서 함수 전달
5. 변수는 불변이다.
함수형 프로그래밍에서 변수가 초기화되면 수정할 수 없다. 새로운 변수를 만들 수는 있지만, 기존 변수를 수정할 수는 없다.
이렇게 하면 프로그램의 런타임 동안 상태를 유지하는 데 도움이 되고, 변수를 만들고 값을 설정하면 해당 변수의 값이 절대 변하지 않는다는 것을 알고 프로그래밍을 하기 때문에 side effect에 대한 우려도 제거된다.
장점
1. 순수 함수는 상태를 변경하지 않고 주어진 입력에만 의존하기 때문에 이해하기 쉽다.
2. 함수를 값으로 처리하고 매개변수로 함수에 전달하는 함수형 프로그래밍 언어의 기능은 코드를 더 읽기 쉽고 이해하기 쉽게 만든다.
3. 테스트 및 디버깅이 더욱 쉽다. 위에서도 언급했듯이 순수 함수는 결과가 입력 매개 변수에만 의존하며, 반환 값 외에는 외부 영향을 미치지 않는 함수이기 때문에 부작용이나 숨겨진 입출력이 없고, 따라서 함수형 프로그래밍을 사용한 프로그램은 디버깅하기 쉽다.
4. 순수 함수는 변수나 외부의 다른 데이터를 변경하지 않기 때문에 동시성/병렬성을 구현하는 데 사용될 수 있다.
단점
1. 코드의 가독성이 저하될 수 있다.
const ret = [1, 2, 3, 4, 5, 11, 12]
.reduce(max, num) => num > max ? num : max, 9)
console.log(ret) // 12
위의 코드는 자연수로 이루어진 배열에서 최댓값을 찾는 예제이지만 reduce라는 순수 함수로 인해 코드를 보자마자 코드의 목적을 바로 파악하기가 쉽지 않다.
2. 루프를 사용하는 대신 재귀적인 스타일로 프로그램을 작성하는 것은 위험할 수 있다.
3. 순수 함수를 작성하는 것은 쉽지만 다른 애플리케이션 및 I/O 작업과 결합하는 것이 어렵다.
4. 불변의 값과 재귀는 성능 저하로 이어질 수 있다.
함수형 프로그래밍의 적용
- 수학적인 계산이 필요한 경우
- 동시성 또는 병렬화가 필요한 경우
References
geeksforgeeks-functional-programming-paradigm
'CS > 개발상식' 카테고리의 다른 글
Git & GitHub (0) | 2022.09.17 |
---|---|
MVC 패턴 (0) | 2022.09.17 |
TDD(Test-Driven Development) (0) | 2022.09.15 |
RESTful API (0) | 2022.09.09 |
객체 지향 프로그래밍의 설계원칙, SOLID (0) | 2022.09.07 |