프로그래밍의 일곱 가지 원형 언어 (2022)
(madhadron.com)- 개별 문법보다 기초 패턴 묶음의 차이가 더 중요하며, 프로그래밍 언어는 반복·재귀·구성 방식에 따라 일곱 가지 원형 언어로 나뉨
- ALGOL, Lisp, ML, Self, Forth, APL, Prolog가 핵심 분류이며, 각 계열은 대표 언어를 기준 표본으로 삼아 다른 언어의 계통을 판단
- 익숙한 원형 언어를 공유하는 새 언어는 배우기 쉽지만, 낯선 원형으로 이동하면 새로운 사고 경로와 상당한 학습 시간 필요
- ALGOL은 대입·조건문·반복문 중심의 함수 조직, Lisp는 매크로와 리스트 코드, ML은 일급 함수와 재귀, Self는 메시지 전달 객체, Forth는 스택 기반 문법, APL은 n차원 배열, Prolog는 사실과 탐색 구조가 특징
- 모든 프로그래머에게 ALGOL 계열 언어 숙련이 우선순위이며, 그다음으로 SQL을 배우고 이후 낯선 원형 언어를 꾸준히 익히는 방식이 장기적으로 유리함
프로그래밍의 일곱 가지 원형 언어
- 프로그래밍 언어를 고를 때는 개별 문법 차이보다 기초 패턴 습득이 더 중요하며, 비슷한 계열 언어 사이에서는 배열 순회나 조합 순회 같은 기본 구조가 거의 같은 형태
- 서로 다른 언어군은 반복, 재귀, 프로그램 구성 방식이 크게 다르며, 이런 기초 패턴 묶음이 서로 다른 원형 언어를 이룸
- 익숙한 원형 언어를 공유하는 새 언어 학습은 비교적 쉬운 전환이지만, 낯선 원형 언어로 이동할 때는 상당한 시간과 새로운 사고 경로 필요
- 소프트웨어 분야에서 인식하는 원형 언어는 ALGOL, Lisp, ML, Self, Forth, APL, Prolog 일곱 가지
- 각 원형 언어는 특정 대표 언어를 기준 표본처럼 삼아 분류하며, 다른 언어들은 그 표본과 비교해 계통을 판단하는 방식
-
ALGOL
- 프로그램이 대입, 조건문, 반복문의 순서열로 구성되며, 함수 단위로 조직되는 형태
- 많은 언어가 여기에 모듈 시스템, 새 데이터 타입 정의 방식, 다형성, 예외나 코루틴 같은 대체 제어 흐름 구조 추가
- 현재 널리 쓰이는 대부분의 프로그래밍 언어가 이 원형 언어 계통에 속하는 형태
- ALGOL 자체로는 ALGOL 58, ALGOL 60, ALGOL W, ALGOL 68 포함
- Assembly language, Fortran, C, C++, Python, Java, C#, Ruby, Pascal, JavaScript, Ada가 이 계통에 연결
- 가장 오래된 원형 언어로, Ada Lovelace의 Babbage 해석기관용 프로그램 정식화까지 거슬러 올라가는 계보
- EDVAC와 초기 Univac으로 이어지는 Eckert-Mauchly 구조 컴퓨터의 기계어와 어셈블리어, Grace Hopper의 A-0부터 Fortran과 COBOL에 이르는 초기 고급 언어 시도가 모두 이 형태
- 1960년대 학계에서 구조적 프로그래밍이 발전하며 이런 언어들을 더 관리 가능하게 만들었고, 그 결과가 ALGOL 60이며 이후 계열 구성원 대부분이 여기서 파생
- 시간이 지나며 다른 원형 언어의 기능을 흡수하는 경향 존재
- 1980년대에는 Self 계열 개념이 클래스 형태로 접목되어 데이터 타입 정의와 다형성 구현 수단으로 사용
- 2010년 이후에는 ML 계열 개념도 등장
-
Lisp
- 괄호로 감싼 전위 표현식과 리스트 표현이 결합된 문법
(+ 2 3)(defun square (x) (* x x))(* (square 3) 3)
- 공백으로 구분된 항목을 괄호로 감싼 리스트 표현이 언어에 내장되어 있어 코드 자체가 리스트 형태
- 매크로가 리스트를 받아 수정한 뒤 수정된 코드를 컴파일러에 넘길 수 있어, 프로그래머가 언어 의미를 재정의할 수 있는 구조
- 대부분의 코드 작성에서는 다른 원형 언어, 보통 ALGOL이나 ML처럼 동작하는 경향이 있지만, 매크로 시스템이 구별점
- Common Lisp의
loop문법도 언어 내장 기능이 아니라 매크로로 정의된 형태 - 초기 Lisp 변종이 많았지만 커뮤니티는 Common Lisp로 합의 형성
- Sussman과 Steele은 함수로 어디까지 가능한지 탐구해 Scheme 생성
- 수치 계산용 Lush, AutoCAD 스크립트 언어 AutoLISP, Emacs 편집 동작 구현 언어 Emacs Lisp 같은 특수 목적 Lisp 사용
- 최근에는 Clojure가 Lisp 계열의 세 번째 주요 분기로 부상
- Fortran보다 약 1년 뒤에 등장한, 오늘날까지 사용되는 두 번째로 오래된 언어 계열
- 출발점은 자기 자신의 식을 평가할 수 있는 수학 구조를 어떻게 표기할지에 대한 수학적 질문
- John McCarthy가 1958년에 답을 제시했고, 이후 컴퓨터에 구현
- 초기 Lisp는 수학적 배경 탓에 당시 기계와 잘 맞지 않았으며, 메모리와 CPU 사이클 문제는 수학에는 없던 주제였고 가비지 컬렉션 같은 기법이 필요해진 상황
- 1970년대 후반과 1980년대 초반에는 Lisp 실행만을 위해 밑바닥부터 설계된 기계가 존재
- 오늘날 통합 개발 환경의 많은 요소가 그 기계들에서 발명
- 같은 시기 인공지능 연구의 주된 수단이 Lisp였고, 1980년대 인공지능 과열이 성과를 내지 못하자 분야와 함께 Lisp도 AI Winter로 추락
- 이후에도 살아남았으며, 컴퓨터 성능 향상과 다른 언어들의 기능 수용으로 구현 난점이 줄어든 상태
- 괄호로 감싼 전위 표현식과 리스트 표현이 결합된 문법
-
ML
- 함수가 일급 값이며, 다양한 함수와 태그드 유니언을 표현할 수 있는 Hindley-Milner 계열 타입 시스템 보유
- 모든 반복이 재귀로 수행되는 형태
sum [] = 0sum (x:xs) = x + sum xs
- 반복 패턴을 캡슐화한 함수를 정의하고, 다른 함수를 받아 동작을 구현하는 방식도 사용
map _ [] = []map f (x:xs) = (f x) : (map f xs)
- 일부 언어인 Miranda와 Haskell은 기본적으로 지연 평가 사용
- 다른 언어들은 타입 시스템을 여러 방향으로 확장
- OCaml은 Self 원형 언어 개념과의 결합 시도
- Agda와 Idris는 값과 타입을 섞는 종속 타입 시스템 채택
- 1ML은 모듈과 타입 결합
- ML에서 CaML, Standard ML, OCaml이 파생
- Miranda, Haskell, Agda, Idris 같은 관련 계열도 이어짐
- ML은 영국 Cambridge에서 개발된 정리 증명 프로그램의 메타언어였으며, 이름도 여기서 유래
- 이후 그 맥락을 벗어나 독자적 언어로 퍼졌고, 특히 영국과 프랑스를 중심으로 유럽에서 인기 확보
-
Self
- 프로그램이 서로 메시지를 주고받는 객체 집합으로 구성되며, 모든 동작이 이 방식으로 구현
- 새 객체는 기존 객체에 메시지를 보내 생성하는 구조
- 조건문도 true 객체와 false 객체 중 하나를 참조하는 변수를 통해 수행
- 두 객체는 참일 때 실행할 함수와 거짓일 때 실행할 함수를 매개변수로 받는 메시지 수신
- true 객체는 첫 번째 함수를, false 객체는 두 번째 함수를 실행
- 호출 코드는 어느 객체인지 모르고 단지 메시지를 전송하는 형태
- 반복문도 같은 방식이며, 적절한 객체를 만들어 적절한 위치에 넣으면 언어 의미 전체 재정의 가능
- 이런 언어들은 보통 소스가 텍스트 파일이 아니라 라이브 환경에 저장
- 프로그래머는 라이브 시스템을 수정하고, 파일을 컴파일해 시스템을 만드는 대신 그 상태를 저장
- 중요한 예시는 Smalltalk와 Self
- 많은 언어가 이 언어군의 메시지 전달 방식을 일부만 도입하며, 이런 부분 도입을 보통 객체지향 프로그래밍이라고 부름
- 이들 대부분은 Smalltalk 기반이며, JavaScript만은 예외로 Self의 클래스 없는 객체 시스템에서 유래
- Common Lisp의 객체 시스템은 메시지를 받는 객체 하나만이 아니라 모든 매개변수를 기준으로 런타임이 실행 코드를 선택하도록 일반화
- Erlang은 실행 흐름이 객체 사이를 옮겨 다니는 대신, 병렬 실행 스레드가 명시적으로 메시지를 듣고 보내는 방향으로 전환
- 원조 언어는 Smalltalk이며, 1970년대 후반과 1980년대 Xerox Parc에서 개발
- 1980년대에는 여러 상용 Smalltalk 시스템이 있었고, IBM은 다른 언어용 프로그래밍 도구인 VisualAge 컬렉션 개발에 Smalltalk 사용
- 오늘날 Smalltalk는 주로 오픈소스 Pharo Smalltalk 형태로 존속
- Smalltalk를 빠르고 효율적으로 실행하는 연구가 많이 진행되었고, 그 정점이 Strongtalk 프로젝트
- Strongtalk의 발견은 Java의 HotSpot JIT 컴파일러 기반이 되었다는 역사적 중요성
- Smalltalk는 이전 언어의 값과 타입 개념을 이어받아 클래스를 구현했고, 모든 객체는 타입을 부여하는 클래스를 가졌으며 클래스가 그 타입 객체를 생성
- Self는 클래스 개념을 제거하고 객체만으로 구성
- 더 순수한 형태라는 이유로 이 원형 언어의 표본으로 Self 선택
-
Forth
- 스택 언어는 Lisp의 역상 같은 형태이며, Hewlett Packard의 역폴란드 표기 계산기 문법과 문법을 공유
- 데이터 스택을 가지며,
42같은 리터럴을 쓰면 스택에 푸시되고 함수 이름은 명시적 매개변수 없이 스택을 대상으로 동작 - 간단한 산술도
2 3 + 5 *처럼 뒤집힌 형태 - 함수 정의도 매우 간결한 형태
- 대부분의 Forth 변종에서
:가 새 단어 정의 square는dup과*호출과 같은 의미dup는 스택 최상단 복제,*는 최상단 두 항목 곱셈
- 대부분의 Forth 변종에서
- 파서를 가로채 자기 코드로 교체할 수 있어 문법 전체 교체 가능
- Fortran 부분집합이나 패킷 레이아웃, 상태 기계 전이를 나타내는 ASCII 다이어그램 직접 파싱 방식 같은 작은 언어를 정의한 Forth 프로그램이 흔한 형태
- Forth의 여러 변종, PostScript, Factor, Joy 포함
- Joy는 스택 대신 합성의 수학적 정식을 쓰는 순수 함수형 언어
- Forth는 1970년에 전파망원경 제어용으로 처음 작성
- 이후 임베디드 시스템 전반으로 널리 확산
- Forth 시스템은 부트스트랩이 충분히 쉬워서 여러 프로그래머가 각자 목적에 맞게 만든 변종이 수십 종 존재
- PostScript는 1980년대 프린터에 문서를 설명하는 유연한 수단으로 등장
- PostScript는 여러 면에서 Forth보다 더 제한적이지만, 그래픽 레이아웃 관련 기본 연산을 언어에 정의
-
APL
- 언어의 모든 것이 n차원 배열
- 연산자는 한두 개의 기호로 구성되며, 배열 전체에 대한 고수준 연산 수행
- 표현이 매우 압축적이어서 기호열 자체가 다른 이름을 붙이지 않아도 연산의 표지가 되는 형태
- 예시로 변수
x의 평균 계산은(+⌿÷≢) x형태 - APL, J, K가 대표 사례
- 배열에 대한 고차 연산은 MATLAB, NumPy, R 같은 여러 환경으로 일부 수출된 상태
- APL은 1960년대 Kenneth Iverson이 만든 수학 표기법에서 시작했고, 이후 컴퓨터에 구현
- 무거운 계산을 수행하는 사람들 사이에서 이후 계속 틈새 지지층 유지
- 후손 언어 K는 금융 환경에서 매우 인기 있었던 형태
-
Prolog
- 프로그램이 사실들의 집합으로 구성
father(bob, ed).father(bob, jane).
- 변수로 다른 사실에서 사실을 유도하는 비접지 사실도 사용
grandfather(X, Y) :- father(X, Z), father(Z, Y).
- Prolog 런타임은 이 사실들과 질의를 받아 결과를 찾기 위해 탐색 수행
- 사실 정의 구조를 적절히 선택하면 튜링 완전성 성립
- Prolog에서 사실을 이루는 항은 그 자체로 고유한 데이터 타입이며, 생성한 뒤 런타임에 넘길 수 있음
- 이 점이 Lisp의 매크로나 Forth의 파서 교체와 유사한 위치
- Prolog 프로그램은 본질적으로 탐색이므로, 데이터베이스 질의처럼 탐색 순서 조정과 성과 없는 경로의 조기 차단을 중심으로 튜닝
- Prolog, Mercury, Kanren 포함
- 이 원형 언어 계열의 실제 프로그래밍 대부분은 Prolog 자체에서 이뤄지며, 커뮤니티의 통일성이 매우 강한 상태
- 1970년대 프랑스의 논리학자들이 프로그램을 1차 논리로 표현할 수 있음을 깨닫고 구현 시도 시작
- 1980년대 일본의 5세대 컴퓨터 프로젝트가 Prolog에 크게 베팅했지만 프로젝트 실패와 함께 Prolog 평판도 하락
- 그와 별개로 수십 년 동안 Prolog 런타임을 대부분의 경우 효율적으로 만들기 위한 연구와 새 기능 추가 연구 지속
- 수치 제약 같은 기능이 더해지며 제약 논리 프로그래밍으로 이어짐
- Prolog는 틈새 영역에서 계속 등장
- Java의 타입 검사는 여러 해 동안 Prolog로 구현
- Facebook의 초기 소스 코드 검색 도구도 Prolog 기반
- 프로그램이 사실들의 집합으로 구성
어떻게 활용할 것인가
- 대부분의 프로그래머에게 이 언어군 일부 또는 전부는 매우 이질적으로 보일 수 있지만, 각각이 만드는 사고 경로와 새로운 가능성을 위해 일정 시간 투자할 가치 존재
- ALGOL 관점에서는 완전히 달라 보이는 두 대상이 다른 관점에서는 사소한 비교가 되는 경우가 매우 흔한 형태
-
우선순위
- 모든 프로그래머는 ALGOL 계열 언어 하나를 잘 알아야 하는 상태
- 그다음으로 Prolog 계열 언어인 SQL 학습 권고
- 경력에서 ALGOL 다음으로 가장 큰 효용을 준다는 위치
-
이후 확장
- 위 두 계열을 익힌 뒤에는 매년 낯선 원형 언어 계열의 새 언어 하나를 배우는 방식이 장기적으로 이득
- 각 계열에서 제안된 언어와 순서는 다음과 같은 형태
- Lisp: PLT Racket
- ML: Haskell
- Self: Self
- Prolog: Prolog
- Forth: gForth
- APL: K,
ok를 통해 사용
-
순서 조정
- 수치 계산을 많이 한다면 K를 더 일찍 배우는 편이 적합
- 임베디드 프로그래밍이 많다면 gForth를 더 일찍 배우는 편이 적합
- 다만 순서 자체나 정확히 어떤 언어를 고를지는 중요하지 않은 상태
- Haskell 대신 Standard ML이나 OCaml, PLT Racket 대신 Common Lisp, gForth 대신 Factor를 배워도 무방한 범주
-
각주에 포함된 보충
- SQL을 배운 뒤에도 Prolog 자체를 여전히 배울 필요 존재
- 실제 사용 방식이 SQL과 상당히 다르기 때문
- Forth를 깊이 이해하려면 Forth 구현체를 직접 만들어보는 접근이 일반적이라는 독자 의견 포함
- Forth는 한 사람이 비교적 짧은 시간 안에 바닥부터 구현할 수 있을 만큼 작다는 언급
- gForth는 ANS Forth를 배우기 좋은 구현체
- 학습 자료로 McCabe의 FORTH Fundamentals, Volume 1 언급
- 함께 살펴볼 Forth로 PygmyForth, eForth, colorForth 언급
- SQL을 배운 뒤에도 Prolog 자체를 여전히 배울 필요 존재
Hacker News 의견들
-
Tufts의 PL 수업에서 명령형, Lisp, ML, Smalltalk 앞의 4개 계열 언어를 각각 미니 버전으로 직접 만들어봤고, 그 과정이 이제 교재로도 나와 있어 반가움. 예전에는 Prolog 파트도 있었는데 빠진 점은 아쉬움
- 혹시 빠진 Prolog 파트 포함판이 Internet Archive 같은 곳에라도 올라오면 정말 좋겠다는 생각임
-
이 글의 분류에서 하나만 고치자면, Ruby는 Algol 계열이라기보다 명확히 객체지향 언어라고 봄. Smalltalk의 영향이 크고, 표준 라이브러리 이름도
map보다collect같은 식으로 그 흔적이 남아 있음. Ruby는 처음부터 끝까지 모든 것이 객체이고, 메서드 호출도 객체에 메시지를 보내는 개념으로 이해하는 쪽이 자연스러움. Python과 자주 비교되지만 진화 경로는 꽤 달랐고, 지금은 비슷한 생태계 지점으로 수렴한 느낌임. 내겐 Ruby가 Python보다 더 포근한 알파카처럼 느껴짐- Python도 new style classes 이후로는 사실상 순수 OOP 언어라고 볼 수 있음.
Hello World수준에선 티가 덜 나도, 기본형까지 전부 객체가 되었음. OOP를 싫어하는 사람들에게type(42)와dir(42)를 보여주면 정수조차 객체라는 점을 강조하기 좋음 - 특정 원형 언어 하나를 객체지향 언어라고 딱 찍는 방식이 오히려 사람들을 헷갈리게 한다고 느낌. OO는 절차형처럼 하나의 프로그래밍 스타일에 가깝지, Python과 C++를 다중 상속이 있다는 이유만으로 같은 종류의 언어라고 묶는 건 무리라고 봄
- 낙타 비유를 보니, camel은 원래 Perl 쪽 상징 아니었나 싶음
- Python도 new style classes 이후로는 사실상 순수 OOP 언어라고 볼 수 있음.
-
나는 언어 계보에 증명 표현용 언어라는 부류를 하나 더 넣고 싶음. Curry-Howard 대응으로 프로그램이 곧 증명이 되는 계열이며 Lean이 대표적 예시임. 함수형의 하위 분류로 볼 수도 있지만, 주된 목적이 실행보다 검증이라는 점에서 별도 축으로 다룰 가치가 있다고 느낌
- 내 눈엔 정리 증명과 복잡한 타입은 기존 언어에 얹힌 확장처럼 보임. Agda, Idris는 복잡한 타입이 추가된 함수형이고, Isabelle·Lean은 거기에 상호작용적 증명이 더해진 형태임. Dafny는 명령형에 정리와 힌트를 얹은 쪽이고, ACL2는 theorem/hint가 붙은 Lisp라고 보면 이해가 쉬움. 또 Rust traits에서 보듯 typeclasses는 함수형·명령형 언어 위에서 돌아가는 일종의 로직 프로그래밍처럼 느껴짐
- 이런 계열은 정의상 튜링 완전성이 없으니 진짜 프로그래밍 언어로 보긴 어렵다고 생각함. 만약 튜링 완전했다면, 종료되지 않는 프로그램으로 거짓 증명을 만들어낼 수도 있기 때문임
- 나는 이 계열이 결국 ML에서 직접 파생된 흐름이라고 봄
- Lean은 분명 Agda, Idris와 가까운 dependently typed ML-family 언어라서 크게 보면 ML 분류 안에 넣을 수 있다고 생각함. 그리고 Lean의 장기 목표가 실행은 부차적이라는 식도 아닌 듯함. Microsoft가 실제 소프트웨어 작성에 관심을 두고 있음. 반대로 “증명을 표현하는 언어”라는 점을 더 강조하면 Prolog도 빠질 수 없어서, Lean을 ML 반, Prolog 반처럼 볼 수도 있음. 이 관점에선 Curry-Howard 대응은 계산 논리를 구현하는 한 가지 방식이라는 느낌임
-
최근에 언어 비교 프로젝트를 다시 살펴봤는데, 10개 문자에 대한 3,715,891,200개의 signed permutation을 병렬로 순환 분해하는 벤치마크였음. “원형 언어”보다는 각 패러다임의 현대적 구현체 중 연구용 프로그래밍으로 실제 선택할 만한 언어를 찾고 싶었음. 성능뿐 아니라 AI 도움을 받기 쉬운지, 내가 코드를 읽고 사고하기 편한지도 같이 봤고, AI 덕분에 각 언어를 꽤 깊게 최적화해보는 일종의 관광도 가능했음. 결과는 여기에 정리했고, 특히 F#이 맨 위에 나온 건 꽤 놀라웠음
- 얼핏 보면 의외지만, 디테일이 핵심이라고 생각함. Lean을 빼면 전반적으로 수치 차이가 아주 극적이지 않고, Chez가 C++보다 2.5배 느린 것도 동적 타입 JIT 언어치곤 꽤 선방한 편임. F#이 이런 작업에서 강한 건 .NET Core 위의 병렬 처리 경험이 특히 성숙하고 무난해서일 가능성이 커 보임. 만약 이 수치가 elapsed time이라면 CPU time 분해도 함께 보면 더 흥미로울 듯함. 또 언어별 병렬화 전략이 조금씩 달라서 완전히 같은 조건 비교는 아님. 예를 들어 F#의 단순한 스레드 분기와 Rust의 Rayon 병렬 iterator는 오버헤드 구조가 다를 수 있음. 결국 Rust와 C++는 저수준 OS 동시성 primitive를 세심하게 다루면 더 빨라질 수도 있지만, 그건 또 다른 종류의 비교가 됨. C나 Haskell의 C FFI 활용을 허용할지도 애매하고, 그래서 이런 비교는 본질적으로 정성적 판단이 많이 섞임. 참고로 Chez 코드는 permutation을 fxvector에 담고 fixnum 전용 연산을 쓰면 boxing/unboxing과 할당을 줄여 더 빨라질 여지도 있어 보임. 관련 문서는 Chez Scheme 객체 문서에 있음
-
나도 비슷한 글을 여기에 쓴 적 있음. Algol, Lisp, Forth, APL, Prolog에는 동의하지만, 혁신적인 함수형 언어로는 ML보다 약간 앞선 SASL을 넣었고, 객체지향 대표로는 Self보다 먼저 나온 Smalltalk를 골랐음. 여기에 Fortran, COBOL, SNOBOL, Prograph까지 각자 다른 방식으로 판을 바꾼 언어라 생각해 함께 포함했음
- 나는 이 목록이 더 마음에 듦. 특히 SNOBOL이 들어간 점이 반가움. 직접 써본 적은 없지만, 어릴 때 공공도서관 책 세일에서 이름이 재밌어서 관련 책을 집어 들며 처음 알게 된 언어 중 하나였음. 그전엔 BASIC, Logo, 그리고 Atari BASIC 매뉴얼 예제를 따라 BASIC에서 호출해본 정도의 6502 어셈블리만 조금 알았음. 또 혁신적인 언어 목록에 Fortran과 COBOL, 혹은 그 뿌리인 FLOW-MATIC이 빠지는 건 상상하기 어렵다고 느낌. 참고한 책은 Atari BASIC manual 쪽이었음
- 왜 Self 대신 Smalltalk가 목록에 들어가지 않았는지 이해가 잘 안 됨. Smalltalk가 더 먼저였고, Alan Kay가 “OOP”라는 이름 자체를 만든 인물이기도 함. ML도 계보상 Lisp의 자식으로 보는 편임
-
나는 이 논의에 의미론적 계열을 더 추가하고 싶음. Verilog, Petri nets, Kahn process networks, dataflow machines, process calculi, reactive, term rewriting, constraint solver/theorem prover 계열, probabilistic programming 같은 것들임. 또 기존 7분류에 딱 맞지 않지만 실제로는 생산 단계에 가까운 Unison, Darklang, temporal dataflow, DBSP 같은 언어도 떠오름. 다소 반칙처럼 보일 수 있지만, 대부분 von Neumann식 기계 모델과 평행한 계산 모델이기 때문임. 나는 한동안 “우리가 아는 모든 계산 방식, von Neumann 너머” 같은 글을 써보고 싶었음
- 그런 글이 나오면 정말 기쁘게 읽을 것 같음. 그 사이에 Steve Yegge 글 일부를 다시 떠올리게 됨. 요지는 현대 CS 교육의 대부분이 사실상 von Neumann이 만든 틀 위에 있고, 순차 장치를 택한 것도 당시 제조 비용과 속도 현실을 반영한 선택이었다는 점임. 또 우리가 배우는 기계 구조, 분기, 반복, 서브루틴, 디버깅, 수 체계 변환, 문제 모델링 같은 많은 요소가 이미 그의 작업에서 나왔다는 내용이 인상적이었음. 관련 인용은 archive에 있음
- term rewriting 얘기를 보니 대학 때 스프레드시트 소프트웨어를 만들며 수식 파서를 맡았던 기억이 남. 처음엔 일주일 내내 막혔는데, 결국
1+1을ADD(1,1)같은 형태로 재작성하면 내가 아는 방식으로 파싱할 수 있다는 걸 깨달았음. 게다가 regex 배우기를 괜히 거부해서 코드가 꽤 기묘해졌고, 동료가 “Andy가 된다니까 건드리지 말자”라고 했던 말이 아직도 기억남. 다른 팀 사람은 regex로 내 코드보다 20배쯤 짧게 끝냈음 - “실전 준비가 된 신흥 언어”라는 말에 덧붙이자면, 내 기준엔 아직 완전히 production-ready는 아니어도 실제 현업에서 쓰이는 ChatGPT 같은 시스템도 비슷한 범주로 보임. 이것들을 프로그래밍 언어로 볼지는 논쟁적이지만, 사람이 컴퓨터에 뭘 하라고 지시하는 매개라는 점에선 충분히 그렇게 볼 수 있다고 생각함. 비결정적이라는 점도 프로그래밍 언어의 필수 조건은 아니라고 봄
- Sussman의 propagators 관련 글도 재미있게 볼 만하다고 생각함
- S9 Scheme에서의 logic programming 예제로는 이 자료가 괜찮았음. 책을 꼭 사지 않아도 코드를 바로 받아볼 수 있고, Simply Scheme 같은 입문서로 기초만 익힌 뒤 적용하면 솔버 구조가 꽤 쉽게 읽힘
-
TU Delft에서 들었던 “Concepts of programming languages”가 내가 컴공에서 제일 좋아한 과목이었음. C, 함수형 쪽으로 Scala, 프로토타입 개념으로 JavaScript를 배웠고, 덕분에 몇 년 뒤 Elixir를 익힐 때 훨씬 수월했음. 또 Unreal Tournament 에이전트를 GOAL이라는 Prolog 기반 언어로 짜는 수업도 있었음. 나는 오랫동안 Prolog를 어디에 써야 할지 감을 못 잡았는데, 결국 LLM이 생성한 형편없는 Papiamentu 문장을 반복적으로 고치게 만드는 spellcheck를 만드는 데 활용하게 되었음
- 나도 비슷한 수업을 들었고, 교수는 별로였어도 수강한 걸 아주 잘했다고 느낌. 다른 원형 언어들을 아주 얕게라도 알고 있는 것만으로도 시야가 넓어지고, 어셈블리까지 더하면 더욱 그 효과가 큼. 직접 뭔가 생산적으로 쓰진 못해도, 망치만 들고 모든 문제를 못처럼 보는 함정은 피하게 됨
- 나도 그 수업에 있었음. Unreal Tournament 쪽은 내가 본 것 중 제일 멋진 수업 중 하나였고, 내 다음 해에 없어졌던 걸로 기억함. 지금은 다들 하는 평범한 AI 수업이 된 듯해 아쉬움. 나는 여전히 Prolog의 좋은 활용처를 많이 찾진 못했지만, GOAL 쪽에는 훨씬 더 큰 인상을 받았음. 그리고 최근에서야 그 구조를 더 “보통의” 언어에서도 재현할 수 있고, 그러면 장점도 많다는 걸 깨달아 조금 허탈했음
- 여기서 말한 GOAL이 Game Oriented Assembly Lisp인지 궁금했음
-
나는 “서로 다른 부류의 언어를 배워야 한다”는 주장에 동의함. OCaml을 배우고 나서야 함수가 정말 수학적 함수처럼 느껴졌고, Mathematica는 식 자체를 입력으로 바라보는 습관을 길러줬음. PostScript의 역폴란드 표기법은 단순 산술을 넘어 사고방식을 아예 다시 배선한 느낌이었음. 다만 Java, C#, C++, Python, Ruby 중 무엇을 골라도 상관없다는 주장에는 동의하지 않음. 퀵소트 구현 정도가 목표라면 비슷할 수 있어도, 실제로 뭔가를 만들려는 사람에게는 언어 선택이 밤과 낮만큼 큰 차이를 냄. 3D 게임을 만들고 싶은 사람에게 Ruby를, 탐색적 데이터 과학이나 딥러닝을 하려는 사람에게 Java를 먼저 쥐여주면 의욕이 꺾일 수 있음
- 나도 아마 Rust로 돈 벌 일은 없겠지만, 배운 걸 전혀 후회하지 않음. Rust는 프로그램 안에서 데이터 소유권을 정말 깊게 생각하게 만들어줬음
-
이 글을 보니 Bruce Tate의 7 languages in 7 weeks가 떠오름. 나도 그 책으로 Erlang을 처음 접했음. 다만 역사적으로 COBOL과 Fortran을 Algol 계열로 넣는 건 조금 무리라고 느껴지고, 그래도 역사는 본래 어느 정도 환원적 정리라는 점을 상기시켜주긴 함
- 더 거슬러 올라가 원시적인 분류를 잡는 것도 무리라고 봄. 최초의 assembly 언어들도 명령형이었지만, Algol·Fortran·Cobol을 흥미롭게 만든 건 함수와 다른 고수준 기능으로 복잡한 프로그래밍을 가능하게 했다는 점이었음. 후손은 Algol이 가장 많지만, 최초의 명령형 프로그래밍 언어는 Fortran이라고 생각함
- Wikipedia만 보면 Fortran과 Algol이 둘 다 1957년 전후에 개발된 듯한데, 실제로는 어느 쪽이 더 빠른지, 그리고 설계 과정에 서로 영향이나 중첩이 있었는지 궁금했음
- 차라리 COBOL은 살아 있는 화석처럼 보는 편이 맞지 않나 싶음. 그리고 오늘날의 Fortran은 FORTRAN 계열을 바탕으로 Algol 계보의 특징을 수평 전이받은 언어처럼 느껴짐
-
관련해서 예전 HN 토론도 있었음. 이전 논의를 같이 보면 맥락 파악에 도움 됨
- 정확히는 2023년 5월 4일 토론이고 댓글은 323개였음. 더 오래된 것으로는 2021년 9월 30일의 이 스레드도 있었고, 그때는 29개 댓글이 달렸음