함수형 프로그래밍의 역사

the rise and fall and rise of functional programming

Posted by mido on 2018-03-20

이 글은 Eric Elliottmedium에서 연재하는 Composing Software 시리즈를 번역한 것입니다. [원문보기]

Smoke Art Cubes to Smoke — MattysFlicks — (CC BY 2.0)

참고 : 이 글은 JavaScript ES6+의 함수형 프로그래밍 및 소프트웨어 합성 방법론을 기초부터 다루는 "소프트웨어 합성"시리즈의 제 1 부입니다. 앞으로 계속하여 연재될 것입니다.
<< Part 1에서 다시 시작 | 다음>

전 6 살 때 가장 친했던 친구와 컴퓨터 게임을 하며 많은 시간을 보냈습니다. 그의 집에는 저를 유혹하는 컴퓨터로 가득 찬 방이 하나 있었고 우리는 많은 시간을 들여 거의 대부분의 게임을 탐험했습니다. 어느날 저는 친구에게 "게임을 만드려면 어떻게 해야 할까?"라고 물었습니다.

둘다 게임 개발에 전혀 아는게 없었고 친구의 아버지에게 여쭤보았습니다. 그러자 그분은 높은 선반에 올라가 BASIC으로 쓰여진 게임에 관한 책을 꺼내주셨 습니다. 그 때부터 프로그래밍이라는 기나긴 여정을 시작했습니다. 학교에서 대수학을 배우기도 전에 프로그래밍을 통해 주제를 다 익힐 수 있을 정도였습니다.

합성 가능한 소프트웨어의 부상

컴퓨터 과학의 초기, 대부분의 연구가 실제 컴퓨터에서 이루어지기 전 Alonzo Church와 Alan Turing이라는 두 명의 위대한 컴퓨터 과학자가 있었습니다. 그들은 서로 다른 동시에 동등한 두가지 보편적인universal 계산 모델을 만들었는데, 두 모델 모두 계산가능한 모든 것을 계산할 수 있었습니다.

Alonzo Church는 람다 대수를lambda calculus 만들었습니다. 람다 대수는 함수 합성을 기반으로 하는 계산의 보편적인 모델입니다. Alan Turing은 튜링 머신로 유명합니다. 튜링 머신은 이론상으로 존재하는 기계이며 테이프의 기호을 조작하는 보편적인 계산 모델입니다.

그들은 함께 람다 대수와 튜링 머신이 결국 같은 것임을 보여주기 위해 협력했습니다.

람다 대수는 함수 합성에 관한 것입니다. 함수 합성의 관점에서 생각하는 것은 소프트웨어를 작성하는데 있어 매우 직관적이고 표현적인 접근방식입니다. 이번 편에서는 소프트웨어 설계에서 함수 합성이 얼마나 중요한 지 논의 할 것입니다.

람다 대수를 특별하게 하는 세 가지 중요한 점이 있습니다 :

  1. 함수는 항상 익명입니다. JavaScript에서 const sum = (x, y) => x + y 의 오른쪽은 익명의 함수 표현식 (x, y) => x + y 입니다.
  2. 람다 대수의 함수는 단일 입력 만 허용합니다. 그들은 단항입니다. 하나 이상의 매개 변수가 필요한 경우 함수는 하나의 입력을 받아 다음 함수를 사용하는 등의 새로운 함수를 반환합니다. n 항 함수 (x, y) => x + yx => y => x + y 와 같은 단항 함수로 표현 될 수 있습니다. 다항n-ary 함수에서 단항 함수로의 변환은 currying으로 알려져 있습니다.
  3. 함수는 first class이므로 함수를 다른 함수에 대한 입력으로 사용할 수 있으며 함수는 함수를 반환 할 수 있습니다.

이러한 특성들로 기본 빌딩 블록을 구성하게되면 소프트웨어를 작성하기위한 간단하면서도 표현력있는 어휘가 됩니다. JavaScript에서 익명 함수 및 currying은 선택사항입니다. JavaScript는 람다 대수의 중요 특성을 지원하지만 강제하지는 않습니다.

고전적인 함수 합성은 한 함수의 출력을 가져 와서 다른 함수의 입력으로 사용합니다. 예를 들어, 합성 :

1
f . g

다음과 같이 구현할 수 있습니다 :

1
compose2 = f => g => x => f(g(x))

사용 방법은 다음과 같습니다.

1
2
3
4
double = n => n * 2  
inc = n => n + 1

compose2(double)(inc)(3)

compose2() 함수의 첫번째 인수로 double 함수를 사용하고 두 번째 인수로로 inc 함수를 사용합니다. 그리고 마지막으로 인수 3 을 적용apply합니다. compose2() 함수 서명function signature을 다시 보면, fdouble() , ginc() , x3 입니다.compose2(double)(inc)(3) 은 실제로는 3 세번의 호출과정을 거칩니다.

  1. 첫 번째는 double 을 받고 새 함수를 리턴합니다.
  2. 리턴 된 함수는 inc 를 받고 새 함수를 리턴합니다.
  3. 다음에 리턴 된 함수는 3 취하여 f(g(x))를 평가하는데, 이제는 double(inc(3)) 됩니다.
  4. x3으로 평가되고 inc() 로 전달됩니다.
  5. inc(3)4로 평가됩니다.
  6. double(4)8 로 평가됩니다.
  7. 최종적으로 8이 리턴됩니다.

소프트웨어가 합성되면 합성 함수 그래프로 나타낼 수 있습니다.

1
2
append = s1 => s2 => s1 + s2  
append('Hello, ')('world!')

위 코드를 시각적으로 표현한 것입니다.

람다 대수는 소프트웨어 설계에 엄청난 영향을 주었고 1980년 이전 컴퓨터 과학분야에서 영향력있는 많은 사람들은 함수를 합성하며 소프트웨어를 작성했습니다. Lisp은 1958 년에 만들어졌고 람다 대수의 영향을 많이 받았습니다. 오늘날, Lisp은 여전히 ​​널리 쓰이는 두 번째로 오래된 언어입니다.

저는 AutoLISP으로 Lisp을 처음 접했습니다. 이는 CAD 소프트웨어 인 AutoCAD에서 사용하는 스크립트 언어입니다. AutoCAD는 인기가 높으며, 거의 모든 CAD 응용 프로그램애플리케이션이 AutoLISP를 지원하므로 호환성이 좋습니다. 또한 Lisp은 컴퓨터 과학 커리큘럼에서 인기있는 교육용 언어이기도합니다.

  1. Lisp은 매우 단순해서 하루 만에 기본 문법과 의미를 배울 수 있습니다.
  2. Lisp은 모두 함수 합성에 관한 것이고, 함수 합성은 어플리케이션을 구조화하는 우아한 방법이다.
  3. 제가 아는 최고의 컴퓨터 과학 교과서는 Lisp 을 사용합니다 : 컴퓨터 프로그램의 구조와 해석

합성 가능한 소프트웨어의 몰락

1970 년에서 1980 년 사이에 소프트웨어 작성 방법이 단순히 합성하는 것에서 벗어나 컴퓨터에게 일련의 명령Instruction을 내리는 방식으로 바뀌었습니다. 그리고 객체지향 프로그래밍(OOP)이 등장했습니다. 구성 요소를 캡슐화 하고 메세지를 전달한다는 위대한 아이디어는 대중적인 프로그래밍 언어들에 의해 왜곡되었습니다. 이들은 기능을 재사용하기 위해 상속에 의한 계층 구조와 is-a관계라는 끔찍한 아이디어를 생각해냈습니다.

결국 함수형 프로그래밍은 학계로 밀려났습니다. 괴짜 중의 괴짜 프로그래머들, 아이비 리그의 교수들, 그리고 1990 ~ 2010년대의 강제 자바 수용 메타에서 탈출 한 일부 운 좋은 학생들만이 사용하게 되었습니다.

30년의 암흑기 동안 대부분의 사람들에게 소프트웨어를 만드는 것은 마치 악몽과 같았습니다.

합성 가능한 소프트웨어의 부상

2010년 경 JavaScript의 사용이 폭발적으로 증가했습니다. 2006년 이전 JavaScript는 웹 브라우저에서 귀여운 애니메이션을 만드는 데 사용되는 장난감 언어로 취급받았지만 사실 강력한 기능이 숨겨져있었습니다. 즉, 람다 대수의 중요한 특징들이 포함되어 있었습니다. 사람들은 "함수형 프로그래밍"이라는 새롭고 멋진 무언가에 대해 그림자 속에서 속삭이기 시작했습니다.

2015년, 함수 합성으로 소프트웨어를 개발하려는 아이디어가 다시 인기를 얻었습니다. JavaScript는 10년 만에 이루어진 첫 번째 주요 업그레이드에서 화살표 함수를 추가하여 함수, currying 및 lambda 표현을 쉽게 읽고 만들 수 있게 했습니다.

함수형 프로그래밍 붐에서 JavaScript의 화살표 함수는 로켓 연료와 같았습니다. 오늘날 널리 쓰이는 응용 프로그램애플리케이션들 중에서 함수형 프로그래밍 기술이 사용되지 않은 경우는 거의 없습니다.

합성은 소프트웨어의 동작을 명료하게 모델링하는 간단하고 우아한 표현 방법입니다. 작은 소프트웨어 구성 요소들을 합성하여 더 큰 구성 요소와 기능을 만드는 프로세스는 조직화, 이해, 디버그, 확장, 테스트 및 유지 관리가 더 쉬운 소프트웨어를 만듭니다.

다음 글 부터는 여러 예제들을 함께 실습해 볼 것입니다. 어린 시절 우리는 사물들을 가지고 놀며 학습했습니다. 발견의 즐거움을 재발견하십시오. 마술을 부려 볼 시간입니다.

다음: “왜 JavaScript로 함수형 프로그래밍을 배우는가? >”