함수형 프로그래밍

trevor1107·2022년 10월 16일
0
post-thumbnail
post-custom-banner

함수형 프로그래밍(Functional Programming)이란?

위키백과에 따르면 함수형 프로그래밍은 자료 처리를 수학적 함수의 계산으로 취급하고 상태와 가변 데이터를 멀리하는 프로그래밍 패러다임의 하나이다.

  • 함수의 응용을 강조한다.
  • 선언형 프로그래밍 패러다임을 따르고 있다.
    프로그램이 어떤 방법으로 해야 하는지를 나타내기보다 무엇과 같은지를 설명하는 경우에 "선언형"이라고 한다. 예를 들어, 웹 페이지는 선언형인데 웹페이지는 제목, 글꼴, 본문, 그림과 같이 "무엇"이 나타나야하는지를 묘사하는 것이지 "어떤 방법으로" 컴퓨터 화면에 페이지를 나타내야 하는지를 묘사하는 것이 아니기 때문이다.
  • 1930년대에 계산가능성, 결정문제, 함수정의, 함수응용과 재귀를 연구하기 위해 개발된 형식체계인 람다 대수에 근간을 두고 있다. 다수의 함수형 프로그래밍 언어들은 람다 연산을 발전시킨 것으로 볼 수 있다.
  • Hope같은 최초의 순수 함수형 언어는 상업적 소프트웨어 개발보다는 학계에서 많은 관심을 받았다. 하지만 커먼 리스프, 스킴, ISLISP, 클로져, Racket, 얼랭, OCaml, 하스켈, 스칼라, F# 같은 주요 함수형 언어들은 광범위한 기관에서 산업적이고 상업적인 응용 프로그램 개발에 사용되고 있다.

선언형(Declarative)과 명령형(Imperative)의 차이점

선언형What, 명령형How에 집중하는 것이다.

선언형은 원하는 결과를 표현하기 위해 코드를 작성한다. 선언형 코드의 좋은 예시는 CSS!!

body {
	font-siez:1rem;
	color:skyblue;
}

직관적이다! what에 대해서만 작성할 뿐, how에 대해서는 작성하지 않는다.
선언형 코드는 원하는 결과값을 선언하는 것이다.

명령형은 원하는 결과를 얻기 위해 필요한 지침에 따라 코드를 작성한다.

function spaceToDelimiter(text, delimiter = '❤') {
  let result = '';
  for (let i = 0; i < text.length; ++i) {
    if (text[i] === ' ') {
      result += delimiter;
    } else {
      result += text[i]; 
    }
  }
  
  return result
}

명령형 코드결과값에 어떻게 도달하는 것인가에 대한 작성이다.

위의 명령형 코드를 선언형 코드로 바꾸면 아래와 같다.

function spaceToDelimiter(text, delimiter = '❤') {
  return text.replaceAll(' ', delimiter);
}

String.prototype.replaceAll()를 선언하여 사용했는데, 내부 구현은 어떻게 되어있는지 정확히 모른다. 어떻게 사용하는지만 익혀서 선언형 코드로 바로 적용할 수 있다.

순수한 함수(pure function)

순수한 함수란, 부작용(side-effect)이 없는 함수, 즉, 함수의 실행이 외부에 영향을 끼치지 않는 함수를 뜻한다. 따라서 순수한 함수는 스레드에 안전하고, 병렬적인 계산이 가능하다.

다음과 같은 코드에서 f는 순수한 함수라고 하자.

y = f(x) * f(x);

이 때, f가 두 번 중복되는 것을 다음과 같이 최적화할 수 있다.

z = f(x);
y = z * z;

이렇게 하면, f(x)를 계산하는 과정이 두 번에서 한 번으로 줄어들지만 두 코드의 결과는 항상 같게 된다.

익명 함수(anonymous function)

익명 함수란, 이름이 없는 함수를 뜻한다. 전통적인 명령형 언어에서는 모든 함수에 이름이 부여되어야만 한다.

예컨대 인수를 제곱하는 함수를 C 언어로 작성한다면 다음과 같이 작성할 수 있을 것이다.

int square(int x) { return x * x; }

C++11에서는 익명 함수를 지원해줘서 위의 코드를 익명함수로 바꾸면 아래와 같다.

[](int x) -> int { return x * x; }

고차 함수(higher-order function)

고차 함수(고계 함수)란, 함수를 다루는 함수를 뜻한다. 사실 함수형 언어에서는 함수도 '값(value)'으로 취급한다. 그러므로 정수 1이나 인수를 제곱하는 함수나 동등한 입장에서 다룰 수 있다. 정수를 함수의 인수로 전달할 수 있듯이 어떤 함수도 다른 함수의 인수로 전달할 수 있다. 마찬가지로 함수의 결과 값으로 정수를 반환할 수 있듯이 함수를 반환할 수도 있다.

예를 들어서 1에서 10까지 숫자로 이루어진 리스트의 각 원소를 제곱하고 싶다고 하자. 명령형 언어에서는 반복문을 이용하여 리스트를 훑어 가며 각 원소를 제곱하겠지만, 함수형 언어에서는 리스트를 다루는 고계 함수로 이를 처리할 수 있다. 다음은 하스켈을 이용하여 이를 수행한 예를 보여준다.

map (x -> x * x) [1..10]

여기서 [1..10]은 1에서 10까지 숫자로 이루어진 리스트다. 고계 함수 map은 첫 번째 인수로 주어진 함수(여기서는 제곱을 수행하는 익명함수)를 두 번째 인수로 주어진 리스트의 각 원소에 적용한 결과 리스트를 반환한다. 위 코드를 수행하면 다음과 같은 결과를 얻을 수 있다.

[1,4,9,16,25,36,49,64,81,100]
profile
프론트엔드 개발자
post-custom-banner

0개의 댓글