난해한 프로그래밍 언어

1 개요

Esoteric programming language, esolang. 일부러 다른 프로그래밍 언어에 비해 사용하기 더럽게어렵게 만든 언어.

제작 이유는 대부분 컴퓨터 프로그래밍 언어+프로그래머의 멘탈의 한계를 테스트하기 위해서, 어떤 개념의 증명으로서, 또는 장난하기 위해서(..)이며 절대로 실용적인 프로그래밍에 적용하기 위한 의도는 아니다. 실제 업무에서 쓰는 프로그래밍 언어는 최대한 다양하게 쓸 수 있으면서도 쉽게 작성할 수 있게 만드려고 애를 쓴다. 당연하다

최초의 난해한 프로그래밍 언어는 제임스 라이언스(James Lyons)와 돈 우즈(Don Woods)가 1972년에 만든 인터칼이라고 한다. 제작 이유는 '자신들이 알고있는 언어들과 완전히 다른 언어를 만들고 싶어서.'좋은 트롤링이다

수학에서는 SKI 가 있다. Sxyz=xz(yz), Kxy=x, Ix=x 라는 3개의 함수로 구성된 언어가 튜링 완전한 언어임이 증명되어있다. 이중에서 I(Identity function) 은 S 와 K 로부터 연역되므로, 사실상 S 와 K 2개로 구성된 가장 심플한 수학적 프로그래밍 언어라 할 수 있다. 여기서, 수학과 프로그래밍의 관점의 차이가 존재하는데, 수학에서는 최소주의 및 뇌 내의 판타지(…)를 충족시켜줄 수 있는것을 선호하며, 오로지 해당 언어의 구조와 범주에만 신경쓴다. 그것으로 특정 프로그램을 만드는게 얼마나 쉬운가, 구현시 퍼포먼스는 얼마나 빠른가같은것들은 전혀 신경쓰지 않는 경우가 태반이다. 덕분에 SKI 는 그것으로 실제 프로그램을 구현하는것이 삽질일지라도 수학에서는 아주 중요하게 취급되고, 다른 esoteric language 들도 이런 측면에서는 어느정도 수학과 관련있는 경우가 많다. 하지만, 어디까지나 구성이 전에없이 새로운 경우에만 해당하고[1], 단순히 기존 언어에다가 명령어 몇개를 넣고빼고 하면서 다른 표현방식으로 치환한 정도에 그치는것들은 수학적으로도 아무런 의미가 없다. 사실 여기있는 대부분의 언어도 구성 자체가 새로운 경우는 없다고 봐도 된다. 뇌내판타지도 완전히 참신하기는 절대 쉬운게 아니며, 성공하면 역사에 남는다. (…)

단 하나의 함수만 사용하는 언어인 Iota도 있다. λx.xSK 로 정의된 함수 U로부터 S와 K를 유도해낸다. (S=U(U(U(UU))), K=U(U(UU))) 다만 U는 함수의 정의에 변수만을 사용한 proper combinator가 아니므로 SKI 와 Iota 중 어느 쪽을 더 '작은' 언어로 볼 것인가는 해석의 여지가 있다.

난해한 프로그래밍 언어들은 다양한 방법으로 프로그래머들을 농락하는데, 대략적으로 다음과 같은 경우가 있다.

  • 루프문, 대입문, 조건문 같은 정상적인 문법 구조를 가지는 경우가 거의 없으며, 포인터, 스택, 큐, 메모리 구조 같은 자료구조에 직접 접근하는 경우가 대부분이다.
  • 최소한의 요소만을 가지고 튜링 완전한 언어를 만들어내는 경우. 즉, 구성요소를 최소화한다. 그 예로, 브레인퍽은 8개의 명령어로, Thue는 명령 1개에 피연산자 2개로 튜링 완전한 언어이다.
  • 이상하거나 무의미한 기호를 이용하는 경우. 그 예로 Whitespace는 오직 공백문자, 탭문자, 줄바꿈문자만을 이용하므로 보통 텍스트 에디터에서는 제대로 읽기도 어렵다. 아희 코드는 무늬만 한글이지, 외계어가 따로 없다.
  • 코드가 코드같지 않거나 표현이 과장된 경우. Shakespeare는 겨우 "Hello, World!"를 출력하는데 코드가 50줄을 넘으며, Chef의 코드는 아예 레시피 형태이다 마시쪙 world. 어둠에Dark는 중2병스럽게 표현을 과장시킨 예.
  • 1차원이 아닌 자료 및 코드 영역을 사용하는 경우. 극단적인 예로 NULL이라는 언어를 들 수 있는데, 이 언어는 0차원 프로그래밍 언어로 하나의 숫자가 하나의 프로그램이며 소인수 분해를 통해 명령을 생성해낸다.[2] 이런 언어들은 대부분 유명한 esolang인 비펀지의 영향을 받은 경우가 많다. 참고로 비펀지의 구조는 2차원 구조.
  • 비결정적으로 동작하는 경우. 즉, 경우에 따라 같은 프로그램이 다른 결과를 내놓는다. 대표적인 예는 Java2K나 Thue. 이 경우는 NFA(비결정적 유한 오토마타 기계)의 컨셉을 활용한 것이 많다.
  • 존재자체가 더러운 경우. 프로그램의 작성이 거의 불가능할 정도로 어렵게 만든 경우가 대부분이다.만든 놈이 더 무섭다 Malbolge가 대표적인 예l을 제대로 발음하자, 소개된 지 무려 2년 만에 첫 프로그램이 나왔을 정도로 악질이다.[3]

참고로 난해한 프로그래밍 언어들의 이름은 무언가의 패러디거나 장난식 이름이 많다. 브레인퍽이라든지(Brainfuck, 즉 강간하기, 혹은 뇌지랄), Ook이라든지(오랑우탄의 울음소리라고 한다).

esolang 위키에 정리된 각종 난해한 프로그래밍 언어로 작성된 Hell World Hello, world!

2 예시

  • A: 알파벳 A만으로 프로그램을 작성한다.
  • A[4] - 전체가 난해한 특수문자라 치는 것과 쓰는 것 모두가 어렵다.
  • ArnoldC: 아놀드 슈워제네거영화속 명대사 (One-liner)들로만 이루어진 언어. 예를 들어 Return 커맨드는 I'LL BE BACK, EqualTo는 YOU ARE NOT YOU YOU ARE ME, 그리고 False 커맨드는 I LIED(...)다.
  • asdf : 말그대로 a s d f 4개로 프로그래밍을 한다.
  • Dark : 명령어가 전부 부정적인 단어들로 대치되어있다. 중2병 컨셉으로 traceon이라는 명령어는 대표적인 중2병 게임 Fate/stay night의 주인공 에미야 시로에서 따온 것이다. #
  • ETA
  • FiM++ : My Little Pony: Friendship is Magic의 팬들에 의해 만들어진 언어로, 트와일라잇 스파클셀레스티아 공주에게 보내는 우정 보고서를 바탕으로 실제 편지글처럼 읽을 수 있는 것을 목적으로 한 언어이다. 예를 들어서 편지의 수신자는 곧 클래스의 이름이 되고, hello world!는 I said “Hello World”!가 된다. Java의 문법을 자연어로 치환한 것이라 자바와 완벽하게 1:1 대응이 되도록 제작중이다. 특이하게 편지가 소스 코드라는 티가 나지 않도록 하나의 명령에 같은 뜻을 지닌 여러개의 단어가 대응된다.[5] Interpreter 및 샘플 코드는 여기를 참조.
  • Fugue: 이름처럼 실제 악보로 코드를 구현한다.
  • Grass: W, w, v 이렇게 3개의 알파벳만으로 프로그램을 작성한다. 코드가 풀들이 돋아 있는 모습같아서 이런 이름이 되었다고 한다.
  • HDHL - 미국의 Hackers그룹이 만들고 있는 난해한 프로그래밍 언어. 다만 이 경우는 '실용적인 사용을 위해' 만들고 있다.
  • HQ9+: 명령어가 H, Q, 9, + 이렇게 4개뿐이다. H는 "Hello, world!" 출력을, Q는 콰인[6]을, 9는 99 Bottles of Beer on the Wall 가사 출력을, +는 가산기 1 증가를 담당한다. 물론, 이 언어로 제대로 된 프로그래밍은 불가능하다.뭘 기대해
  • ㅇㅈ: 위의 HQ9+와 상당히 유사하다. 명령어는 ㅇ,ㅈ,ㅊ뿐이다. 아희와 같이 한글로 된 언어다.
  • Java2K
  • Kvikkalkul
  • LOLCODE : 홈페이지 비슷한 테마로 Omgrofl이 존재.
  • Malbolge : 이쪽 계열의 끝판왕. 상세는 항목 참조.
  • NVSPL2 브레인퍽과 유사한 언어로, 국산이다. 명령어들이 죄다 한 글자로 이루어져 있지만 비교적 쉬운 축에 속한다.
  • OISC : 단일 명령어 세트 컴퓨터(One Instruction Set Computer)의 약자로, 단 하나의 명령어만으로 튜링 완전하다. 이 짓거리가 가능한 명령어 중 가장 많이 구현되는 Subleq 명령어의 정의는 다음과 같다:
subleq(a, b, c) : 메모리 주소 A에 있는 값에서 메모리 주소 B에 있는 값을 뺀 결과값을 메모리 주소 B에 저장한다. 이 값이 0과 같거나 작으면 메모리 주소 C로 점프한다. 아니라면 다음 명령어를 실행한다.
  • ORK: 이름부터 패기가 넘친다. Objekts R Kool의 약자...라는데 대놓고 포자번식하는 어떤 우주 깡패들을 연상시킨다. 이름에서 보이듯이 객체지향 언어이며, 사실 소스 코드의 보이는 형태 자체는 오크들하고는 별 관련이 없다. C++로 번역하는 것도 가능한 듯 하다.
  • PATH
  • Pxem: 파일 이름이 코드의 역할을 한다. 파일 내용은 비어 있어도 된다.
  • Sclipting : 이솔랭위키 설명. 한글한자, 일부 전각 특수문자를 활용해서 만든 난해한 프로그래밍 언어다. 개발자는 해당 위키의 Timwi라는 유저.
  • Thue
  • NULL : 본격 0차원 프로그래밍 언어. 그냥 숫자를 쳐 넣으면 그것 자체가 프로그램이 된다. 그 숫자를 소인수분해하는것을 통해서 명령을 만들어낸다! # 본격 괴델 수 컴퓨터판
  • 브레인퍽
    • Misa: 미사쿠라어로 프로그램을 작성한다.
    • Ook!
    • Nyaruko 공식 홈페이지: 브레인퍽에서 각 명령어를 아스키 아트로 바꾼 것. 기어와라! 냐루코 양의 오프닝 太陽曰く燃えよカオス에서 아이디어를 얻었다고 한다.
      • (」・ω・)」うー(/・ω・)/にゃー - 포인터를 오른쪽으로 이동
      • (」・ω・)」うー!(/・ω・)/にゃー! - 포인터가 가리키는 수치를 1 증가
      • (」・ω・)」うー!!(/・ω・)/にゃー!! - 포인터를 왼쪽으로 이동
      • (」・ω・)」うー!!!(/・ω・)/にゃー!!! - 포인터가 가리키는 수치를 1 감소
      • CHAOS☆CHAOS! - 포인터가 가리키는 수치가 0이라면 대응하는 'I WANNA CHAOS!'까지 점프한다.
      • I WANNA CHAOS! - 포인터가 가리키는 수치가 0이라면 대응하는 'CHAOS☆CHAOS!' 까지 점프한다.
      • Let's\(・ω・)/にゃー - 포인터가 가리키는 수치를 출력한다.
      • cosmic! - 입력하는 1바이트를 읽는다.
  • 비펀지
  • 셰익스피어 프로그래밍 언어: 코드를 셰익스피어 소설 같이 쓴다.
  • 셰프 프로그래밍 언어: 레시피 형식으로 코드를 쓴다. 코더가 신경을 좀 많이 쓰면 실제 활용 가능한 레시피로 작성할 수 있다!맛은 보장 못한다
  • 아희: 국산 프로그래밍 언어. 한글만으로 프로그램을 작성한다.의도는 좋았다
  • 언람다
  • 인터칼: 최초의 난해한 프로그래밍 언어.
  • 화이트스페이스
  • 호무호무 호무페이지홈페이지
  • Piet: 데이비드 모건마(David Morgan-Mar)란 사람이 몬드리안의 그림을 보고 만든 언어. 도트 노가다로 그림을 그리면 점의 위치와 RGB값이 코드의 역할을 한다. "Hello, World!" 코드는 이렇게 짠다.
더 많은 예술 작품 코드는 여기서 볼수 있다. [1]
  • 기계어 - 코드가 0과 1 뿐이므로 난해한 프로그래밍 언어는 맞지만, 이건 진짜로 쓰려고 만든 것. 실제로 모든 프로그래밍 언어는 최종적으로 이 기계어로 번역된다. 같은 맥락에서 어셈블리어도 현재 기준으로는 드럽게 어렵긴 해도 본 항목의 예시들에 해당되진 않는다. 무엇보다 이 둘은 활발히 쓰였고, 지금도 배울 사람은 배워야 한다. 사실 이 중에서 제일 배우기 쉽다
더욱 많은 언어는 이런 종류의 언어를 다루는 위키[2]를 참조
  1. 여기서 말하는 구성이란 대수적 구조와는 관계없다. 모든 Turing-complete language 는 대수적으로 보면 결국 모두 동일한 구조이다.
  2. 괴델 넘버링을 응용한것이다. 괴델은 괴델 베타함수를 이용하여 inductive structure 를 갖는 모든 클래스의 원소를 하나의 자연수로 표현하였고, 이를 이용하여 프로그램뿐 아니라, 수학 증명 자체도 하나의 자연수로 표현하였다. 이러한 자연수로의 인코딩/디코딩을 이용하여 증명한것이 불완전성 정리 이다.
  3. 반면 컴파일러나 인터프리터 등의 작성은 다른 고급언어보다 오히려 쉬운 편이다. 일반적인 고급언어는 대체로 구조가 복잡하기 때문에 번역기 작성이 어려운 편.
  4. 위의 언어와는 다르다!
  5. 위의 셰익스피어 프로그래밍 언어도 자연어를 사용하지만, 아스키 한글자를 출력하는 명령인 "Speak your mind"가 수없이 반복되는 것을 볼 수 있다.
  6. 프로그램 자신의 소스코드를 화면에 문자열로 출력하는 것.