3P by GN⁺ | ★ favorite | 댓글 1개
  • Cognition은 Lisp와 연결형 언어의 읽기 선행(read-ahead) 문제를 피하려고 완전 후위(postfix) antisyntax를 택한 언어 연구 프로젝트임
  • 핵심 장치인 delimiter, ignore, singlet, falias, crank, metacrank는 프로그램이 자기 토큰화 규칙과 실행 주기를 바꾸게 해줌
  • 부트스트랩은 모든 문자를 단일 토큰으로 읽는 상태에서 시작해, 공백과 개행을 구분자로 쓰는 환경으로 스스로 이동함
  • crankmetacrank는 토큰을 언제 평가하고 언제 쌓아둘지 제어해 # 주석, \ escape, [ quote, ( macro 같은 prefix 문법을 후위 시스템 안에서 정의하게 함
  • Brainfuck 방언도 별도 파서가 아니라 Cognition 단어와 토큰화 규칙으로 구현해, 문법 자체를 코드로 만들고 자동화하는 방향을 보여줌

기존 문법에서 Cognition이 문제 삼는 지점

  • Lisp는 s-expression과 매크로 시스템으로 강력한 메타프로그래밍을 제공하지만, 여전히 고정된 문법의 영향을 받음
    • 왼쪽 괄호는 오른쪽 괄호가 나올 때까지 읽어야 한다는 신호이므로, 언어 안에서 괄호의 역할을 바꾸기 어렵거나 일부 구현에서는 불가능함
    • 이미 읽은 토큰의 구분 방식을 나중에 바꾸려면 많은 문자열 처리가 필요함
  • 현재 입력을 보고 뒤를 더 읽어야 하는 과정이 syntax이며, 기본 읽기 선행을 가정하는 순간 특정 문법 형태에 묶임
  • Cognition은 이를 피하려고 완전 후위 방식의 antisyntax를 사용함
    • 연결형 언어와 비슷하지만, 일반적인 연결형 언어도 대괄호나 문자열 quote 문자 때문에 읽기 선행 문제를 갖는다고 봄
    • Racket의 매크로 시스템은 실행 중 동적 문법 변경이 아니라 전처리를 사용하는 방식으로 구분됨

프로젝트와 기본 아이디어

  • Cognition은 Matthew Hinton과 함께 몇 달 동안 진행한 활성 연구 프로젝트
  • 구현 저장소는 cognition-rust에 있으며, 저장소에는 언어에 대한 논문도 있음
  • 이해에는 파싱, 토큰화, 문법에 대한 배경이 도움이 됨
  • 설명은 “baremetal cognition” 코드에서 출발해 Stem과 비슷한 문법으로 발전하는 흐름을 따라감

Baremetal Cognition과 토큰화

  • baremetal Cognition은 겉보기에는 Brainfuck과 비슷하지만, 더 강한 메타프로그래밍을 할 수 있음
  • 매우 작은 부트스트랩 코드는 공백과 개행까지 의미 있게 사용하며, 초기 상태에서는 모든 단일 문자가 토큰으로 읽힘
  • Cognition은 기본적으로 스택 기반 설계이지만, 스택보다 일반적인 의미로 container라는 용어를 사용함
  • 기본 환경에서는 특별한 falias를 제외하면 어떤 단어도 자동 실행되지 않음
  • delimiter, ignore, singlet

    • delimiter는 토크나이저가 한 토큰의 끝과 다음 토큰의 시작을 알 수 있게 함
    • 단일 문자 delimiter 목록은 Cognition 코드 안에서 수정하고 읽을 수 있음
    • ignore 문자는 각 read-eval-print loop의 토큰 수집 시작 단계에서 건너뜀
    • 기본값은 모든 문자가 delimiter이고 ignore 문자는 없는 상태임
    • delimiter, singlet, ignore 목록은 whitelist/blacklist 플래그로 동작 방식을 바꿀 수 있음
    • 기본 설정은 blacklist delimiter 없음, whitelisted singlet 없음, whitelisted ignore 문자 없음임
    • singlet은 자기 자신을 토큰에 포함한 뒤 토큰 수집을 끝내는 세 번째 토큰화 범주임
  • falias

    • falias는 container에 올라가는 즉시 실행되는 단어 목록임
    • 기본 falias인 f는 container에 쌓이지 않고 container 맨 위 단어를 실행함
    • 예시에서 fd를 실행하면, d는 delimiter 목록을 단어의 문자열 값으로 바꿈
    • 이후 l, g, t, d 같은 문자를 단계적으로 non-delimiter로 만들고, 공백과 개행을 delimiter 및 ignore로 바꾸는 부트스트랩이 이어짐

부트스트랩이 만드는 실행 환경

  • 초기 부트스트랩은 delimiter와 ignore 규칙을 바꿔 최종적으로 공백과 개행이 토큰 delimiter가 되고, 토큰 시작 단계에서 공백과 개행이 무시되는 환경을 만듦
  • 그 뒤 1crank를 읽고, fcrank를 실행해 crank 1 환경으로 들어감
  • 이 과정의 핵심은 실행 중 토큰화 방식을 바꿀 수 있다는 점임
    • delimiter, singlet, ignore 변경을 프로그램으로 자동화할 수 있음
    • 후위 방식이고 읽기 선행이 없기 때문에 표현식 평가 전에 하나 이상의 토큰을 미리 파싱할 필요가 없음
  • falias는 prefix 단어나 기본 단어 자동 실행 없이도 특정 단어를 실행하게 해줌

crank와 metacrank

  • crank는 stack 위 토큰을 어떤 주기로 실행할지 정하는 장치임
  • crank 단어는 숫자를 인자로 받아, 이후 container에 올라오는 매 n번째 단어마다 stack top을 실행함
    • 부트스트랩 마지막의 1 crank는 모든 토큰을 평가하는 환경을 만듦
    • 5 crank 상태에서는 다섯 번째 토큰이 들어올 때까지 단어들이 쌓일 수 있음
  • 예시 코드는 2crank라는 단어를 만들기 위해 unglue, swap, quote, prepose, def를 사용함
    • unglue는 단어 값을 가져오며, crank 같은 builtin의 함수 포인터도 가져올 수 있음
    • prepose는 Stem의 compose와 비슷하지만 앞에 붙이고 VMACRO에 넣음
    • def2crank2를 stack에 놓고 crank builtin을 호출하도록 정의함
  • Cognition의 container와 macro

    • Stem에서는 단어를 stack에 직접 둘 수 있지만, Cognition에서는 평가되지 않은 단어가 container 안에 들어감
    • 이 설계 덕분에 compose 같은 단어가 단일 단어 container와 다른 container를 일관된 API로 다룰 수 있음
    • Cognition의 macro는 Stem quote와 다름
    • macro가 평가되면 crank를 무시하고 내부 모든 요소가 평가됨
    • 단어에 바인딩된 macro를 평가하면 macro 전체가 crank와 무관하게 실행되고 cranker는 한 번만 증가함
    • macro는 crank에 독립적인 코드와 최적화 목적의 expansion에 유용함
  • metacrank

    • n m metacrank는 stack에서 n개 아래의 요소에 대해 주기 m의 평가를 설정함
    • crank0 m metacrank와 같음
    • 토큰 하나당 평가될 수 있는 metacrank는 하나뿐이며, 낮은 metacrank가 우선권을 가짐
    • metacrank와 crank는 파일의 토큰뿐 아니라 단어 정의를 재귀적으로 평가하는 과정에도 적용됨
    • metacrank는 “n개 토큰을 읽은 뒤 이 토큰을 실행하고 싶다” 같은 직접 문법 조작을 가능하게 함
    • prefix 단어를 프로그래밍한 뒤 필요 없어지면 undef할 수 있음
    • 특정 종료 문자가 아니라 특정 토큰 수 이후 멈추는 prefix 문자도 만들 수 있음
    • 사용자 입력을 수학 프로그램에 넣고, 그 출력을 metacrank 같은 문법 시스템에 전달할 수 있음

Stem 방언으로 발전하는 과정

  • Cognition은 부트스트랩 이후 Stem v2에 가까운 문법을 언어 내부에서 점진적으로 구축함
  • 먼저 f를 falias 목록에서 제거하고 ing만 남김
    • f를 직접 stack에 놓으면 실행되기 때문에 ff를 만든 뒤 문자열을 반으로 잘라 두 개의 f를 얻음
    • 이후 f는 false에 해당하는 빈 단어로 정의됨
  • # 주석

    • # 문자는 처음으로 진짜 prefix처럼 동작하는 코드 예시임
    • 이 주석 문자는 newline 전까지의 텍스트를 버리는 prefix로 동작해, 파서가 앞을 읽는 형태의 문법을 만듦
    • 구현은 geti, getd, gets, crankbase, halt, VMACRO cast, singlet, delim 등을 조합함
    • geti, getd, gets는 각각 ignore, delimiter, singlet을 문자열로 가져옴
    • halt는 모든 metacrank를 0으로 만듦
    • VMACRO cast는 stack top의 container를 macro로 바꿈
    • # 정의는 토큰화 규칙을 바꾼 뒤 미래에 토큰화될 단어에 대해 #를 호출하고, 그 주석을 drop한 뒤 원래 crank와 metacrank로 돌아감
  • escape, quote, macro

    • \는 평가될 단어라도 stack에 올릴 수 있게 하는 escape 문자로 정의됨
    • 이후 [ quote 정의가 추가되고, 다시 그 quote를 사용해 재귀 quote가 가능한 더 나은 [ 정의로 자기 자신을 재정의함
    • 후위 def 때문에 이전 정의를 사용해 새 정의를 만들 수 있음
    • 이 패턴은 low-level Cognition에서 자주 쓰이는 개발 방식임
    • (는 macro bracket으로 정의됨
    • macro는 자동 확장되도록 만들어져, 이미 확장된 macro를 단어에 바인딩하는 것이 더 효율적이라고 봄
    • 기능적으로는 같은 방식으로 평가됨
    • expand는 quote나 macro 안의 단어 정의를 unglue로 재귀 확장함
    • 먼저 기본 expand를 정의한 뒤, 더 일반적인 경우를 처리하도록 expand 자신을 사용해 재정의함

Brainfuck 방언

  • Cognition은 발전된 Stem 방언 위에서 Brainfuck 방언을 정의함
  • 실행 예시는 ../crank -s 2 bootstrap.cog helloworld.bf brainfuck.cog
  • brainfuck.cog는 일반적인 의미의 Brainfuck 파서가 아님
    • Brainfuck 단어를 정의함
    • Brainfuck을 토큰화함
    • Cognition 네이티브 환경에서 실행함
  • 이 예시는 Cognition 문법으로 대체 문법을 쉽게 정의할 수 있음을 보여줌
  • Cognition은 기호를 읽고 기호에 따라 동작을 결정하는 대신, metacrank를 사용하는 prefix 문자 자체를 단어로 정의해 문법을 단어 정의 안에 넣음

dialect dialect 구상

  • mkprefix 같은 단어를 상상할 수 있음
    • 예를 들어 [] 두 입력 단어와 어떤 연산을 받아, []를 만날 때까지 그 연산을 적용하도록 자동 정의하는 단어임
  • 이런 구상이 가능한 이유는 metacrankdef가 모두 일반 단어이기 때문임
  • d, i, s까지 포함해 모든 것이 단어이므로, 문법 구현 과정을 자동화하는 더 추상적인 방언을 만들 수 있음
  • 표준 라이브러리에는 아직 구현되지 않았지만, Matthew Hinton과 표준 라이브러리 가능성으로 논의한 항목이 있음
    • 추상 단어를 자동 생성하고 호출하는 metaword
    • 현재 wordlist를 자동 추상화할 word-generator 검색
    • 문제 해결을 위해 추상화 프레임워크를 지시하는 방식

문법을 코드로 다루는 가능성

  • Cognition에서는 문자열 처리가 토크나이저 후처리와 같아, 문자열 연산이 강한 의미를 가짐
  • 잠재 적용 분야로 Symbolic AI, 문법과 grammar 연구, 언어와 metalanguage 프로토타입 실험이 제시됨
  • 설정 파일을 읽는 프로그램, Cognition 기반 shell, Cognition 기반 운영체제 같은 아이디어도 있음
  • 핵심은 Cognition이 “syntax as code”를 가능하게 한다는 점임
    • 문법을 동적으로 프로그래밍할 수 있음
    • 문법 생성 자체를 자동화할 수 있음
  • Metastack과 cd 같은 개념은 다루지 않았고, 후속 글에서 다룰 수 있는 주제로 남아 있음

댓글과 토론

Hacker News 의견들
  • Racket의 reader 계층 설정보다 이 방식이 더 낫다는 설득은 아직 안 됨
    예를 들어 Racket에서는 Datalog 문법을 쓰면서도 다른 Racket 모듈과 상호 운용되는 내장 Datalog 구현을 만들 수 있고, 기본 데이터 모델은 바뀌지 않음
    S-표현식에 갇히지 않고 메타프로그래밍할 수 있으면서도 더 높은 수준에서 처리하는 방식임
    이런 문법 부트스트래핑은 멋지고 연구적으로 가치가 있지만, Racket 접근보다 근본적으로 더 나은지는 모르겠음
    Lisp, Scheme, Racket 매크로는 보통 AST 위에서 동작하지만, Rhombus는 AST 비슷하면서 일부 파싱 결정을 나중으로 미루는 "shrubbery" 위에서 동작해 문법 확장에 약간의 유연성을 줌
    참고: https://docs.racket-lang.org/guide/hash-reader.html, https://docs.racket-lang.org/datalog/datalog.html, Rhombus 논문 https://doi.org/10.1145/3580417
    • Common Lisp의 readtable보다 낫다는 것도 확신이 안 들고, CL readtable보다 Racket의 #lang이 더 쓰기 편하다고 봄
      readtable만으로도 C 컴파일러를 구현할 정도로 강력함: https://github.com/vsedach/Vacietis
    • 기본 예제로 Brainfuck을 쓰는 걸 보면 진지하게 받아들이라는 의도인지 잘 모르겠음
      개인적으로 "metacrank"가 등장하는 부분에서 빵 터졌음
    • Lisp 매크로가 AST 위에서 동작한다는 말은 Lisp에는 맞지 않음
      Emacs Lisp, Common Lisp, ISLISP에서 매크로는 어떤 데이터를 받고 어떤 데이터를 반환할 뿐이고, AST 같은 개념은 없음
      (foo-macro ...)를 호출하면 ...는 임의의 데이터일 수 있음
      예를 들어 (defmacro rev (&rest items) (reverse items))는 매크로 호출의 소스 인자 목록을 받아 뒤집을 뿐임
      (rev 1 2 3 4 +)(rev (rev 10 n -) (+ a 20 b) (rev 30 a *) list)처럼 쓸 수 있고, 실제로는 리스트와 숫자와 심볼이 전달됨
      텍스트도 아니고 AST도 아니며, eval에 계산된 데이터를 넘겨도 같은 방식으로 동작함
      Lisp의 reader는 기본적으로 데이터 계층인 상징식을 읽고, EVAL과 매크로와 다른 기능들은 주로 데이터를 받음
      컴파일러가 내부적으로 AST 표현을 만들 수는 있지만 그건 구현 자유이며, Lisp 언어는 보통 텍스트 문법이 아니라 데이터 문법 위에서 정의됨
      Lisp 인터프리터는 실행 중 텍스트가 아니라 S-표현식을 처리하는 "List Processor"이고, COMPILE도 텍스트가 아니라 S-표현식을 받음
      Racket과 Scheme은 별도의 매크로 시스템을 가짐
  • 글쓴이에게 조언하자면, 가장 중요한 내용을 먼저 두면 글이 훨씬 탄탄해질 수 있음
    실제 프로젝트인 Cognition이 언급되기 전까지 300단어가 넘게 나오고, Lisp 이야기도 좋지만 프로젝트에서 가장 중요한 부분인지 의문임
    정보성 글을 읽을 때는 계속 "내 시간을 쓸 가치가 있나?"를 따지게 되므로, 문서가 무엇에 관한 것인지 처음부터 알려줘야 함
    "Cognition은 사용자가 수정 가능한 문법을 탐구하는 새 언어다" 같은 식이면 충분했을 텐데, 첫 네 단락 이후에도 계속 읽을 가치가 있는지 판단하기 어려웠음
    • 이 언어를 쓰게 될 가능성도 낮고, 설령 쓰더라도 정보는 이 글이 아니라 문서에서 얻을 것임
      시간이 돈이라면 이 글을 읽은 시간은 낭비였다고 볼 수 있음
      인터넷의 모든 콘텐츠가 개인 취향에 맞춰져야 한다고 기대하기보다, 이미 있는 형식에 적응하는 편이 낫다고 봄
      텍스트는 영상처럼 순차적으로만 소비해야 하는 매체가 아니므로, 대각선으로 훑어 흥미로운 부분을 찾고 없으면 버리거나, 있으면 처음으로 돌아가 읽으면 됨
      다양한 글쓰기 방식은 소비하는 정보를 의식적으로 걸러내게 하므로 더 낫고, 수동적으로만 소비하면 머리가 게을러짐
      다만 영상이었다면 동의했을 것임
      영상은 보기 전에 시간을 투자할지 결정해야 하고, 2배속이나 5~10초 건너뛰기가 조금 도와주지만 문제를 해결하진 못함
    • 순서는 꽤 합리적으로 보였음
      먼저 문제를 설명하고 그다음 해법을 소개하는 구조임
      몇 문장만 읽어도 Lisp를 들어본 적은 있지만 Emacs 설정 파일 밖에서는 써본 적 없는 나 같은 사람을 포함해 99.999%가 신경 쓰지 않을 "문제"에 대한 돈키호테식 해법이라는 건 알 수 있었지만, 그래도 그냥 계속 읽었음
    • Lisp 관련 부분이 프로젝트의 가장 중요한 요소는 아니지만, 프로젝트가 풀려는 문제의 종류를 보여주는 역할은 분명히 함
      이런 구간이 없었다면 뒤의 내용은 더 이해하기 어려웠을 것임
    • 개념에는 관심이 있지만, 첫 문장이 Lisp의 S-표현식 문법에 대한 반응으로 필요성을 정당화하는 듯 보여서 맥락을 놓칠까 걱정됐음
      그 배경을 모르면 전체 글의 맥락을 놓칠 수 있고, 이게 허수아비 논증인지도 판단하기 어려움
      그래서 전체가 매우 좁은 필요를 위해 존재하는 것처럼 느껴지는데, 제목은 훨씬 일반적이고 꽤 흥미로운 개념처럼 보임
    • 지금 글도 완전히 괜찮다고 봄
      처음 두 문장 안에서 풀려는 문제가 무엇인지 드러나며, 내 관심을 가늠하기에는 제안된 도입부보다 훨씬 유용함
  • 흥미로운 글이고, 글쓴이들이 여기의 빈정거림에 신경 쓰지 말고 어둠의 마법 의식을 계속해 주면 좋겠음
    다만 개인적으로는 프로그래밍 순수성의 사다리를 올려다볼 때 Forth 정도가 내가 감당할 수 있는 철학적 순수성의 한계임
    • 이 글의 작성자로서, 빈정거림은 신경 쓰지 않고 오히려 꽤 웃기다고 생각해 환영함
      앞으로도 더 많은 어둠의 마법을 계속 다룰 예정임
  • 메타프로그래밍과 프로그래밍은 같은 것임
    다만 모든 Lisp를 포함해 거의 모든 언어가 인용을 잘못 다루고 있고, 웃기게도 m4는 예외임
    Lisp는 매크로로 이 문제를 우회해, 객체 언어 문장으로 표현된 메타 언어 문장을 인용을 무시하고 다루게 해 줌
    이 문제는 객체 언어와 메타 언어에서 공백을 원자의 종료로 취급하면서 둘을 구분하지 않는 데서 생김
    완전 후위식 반문법이라는 Cognition의 방식은 연결형 프로그래밍 언어와 닮았지만, 후위식 언어는 전위식 언어의 쌍대이고 같은 문제를 겪음
    모든 심볼의 항수를 미리 정하고 고차 함수를 쓰지 않거나, 트리를 직렬화할 수 있는 구분자 한 쌍이 필요함
    암묵적인 0차 스택에 의존하는 건 우울증을 고치려고 전두엽 절제술을 하는 것과 비슷함
    • 피드백은 고맙지만, 아직 전체 글을 읽지 않았다면 읽어보는 게 좋겠음
      우리가 어느 정도 새로 만든 것인지는 우리도 모르고, Lisp로 우리가 하는 일을 할 수 있다고 생각한다면 틀렸다는 걸 증명해도 좋음
    • Lisp와 m4에서 인용이 어떻게 다른지 예시가 궁금함
      주장 자체는 흥미롭지만 더 구체적인 것이 필요함
    • 암묵적 스택에 대한 비유는 화려하긴 하지만, 암묵적 스택은 초기 컴퓨터나 계산기 시절부터 있었음
      전두엽 절제술이 고차 처리 능력을 줄이듯, 명령 문자열 계산의 가장 원시적인 방식으로 돌아가는 것도 비슷하다고 볼 수 있음
      https://www.hpmuseum.org/rpnvers.htm
  • Cognition 프로그램이 실행 중에 문법 구조를 정의하고 재정의하며, 그 안팎으로 들어가고 나올 수 있다는 점이 정말 아름답다고 봄
    특히 그 장치가 아주 작다는 점이 좋음
    언어 전문가가 아니라 새로움이 있는지는 모르겠지만, 글을 읽는 내내 작성자들이 언덕을 넘을 때마다 새로운 가능성의 산맥을 발견하는 기쁨이 느껴졌음
    제대로 이해했다면 Cognition으로 진짜로 생각하는 기계를 만들 수 있다는 이야기임
    프로그램이 중단되고 새 명령으로 재시작되지 않아도, 새 입력을 바탕으로 스스로 새로운 하위 루틴을 작성하고 실행할 수 있음
    즉 프로그램이 새 추상화를 만들고 새 API에 연결하면서 학습하고 적응할 수 있다는 뜻임
    나에게는 더 큰 신경망이나 새로운 학습 기법보다 이쪽이 더 흥미로움
  • 전제가 사실이 아님
    Common Lisp에는 reader macro가 있어서 원하는 대로 문법을 바꿀 수 있고, reader macro로 Fortran 문법을 읽는 Fortran 컴파일러도 있음
    Common Lisp에는 읽기 시점의 reader macro, 매크로, 컴파일 시점의 compiler macro가 있고, 이 모든 매크로 언어가 Common Lisp임
    메타프로그래밍은 매크로나 문법과는 큰 관련이 없고, 타입·인터페이스·클래스·메서드 등의 의미론과 의미를 조작하는 능력을 가리킴
    CL 자체가 충분히 강하지 않다면 이를 위해 CLOS, 즉 Common Lisp Metaobject Protocol이 있음
    • 여기서 말하는 것은 CL의 reader macro임
      CL reader macro로 다른 토크나이저를 쓸 수는 있지만, read table 안의 표현식으로 토크나이저 전환을 알려야 함
      Cognition에서는 함수를 호출하면 호출자 문맥의 토크나이저가 바뀌는 것처럼 보임
  • 최소 기계를 고수준 언어의 인터프리터로 부트스트랩하는 실용 예시로 보임
    튜링 기계나 람다 대수 같은 것으로 이런 작업이 중요하다고 배운 이유는, 고수준 언어가 기초 언어와 동등하다는 걸 보여주고 그래서 전자에 대해 추론한 내용을 후자에도 적용할 수 있음을 보이기 위해서였음
    떠오르는 첫 예이자 유일한 예는 정지 문제임
    실용적 규모에서는 기본 언어에 메모리 누수가 없음을 증명하면 파생 언어에도 누수가 없다고 할 수 있을까?
    이런 식의 부트스트래핑에는 어떤 장점이 있는지 궁금함
    답이 단순히 에베레스트 등반처럼 "거기 있으니까"라면 그것도 존중함
  • df 뒤의 공백, 줄 3의 공백, 줄바꿈이 중요하다는 부분에서 바로 "고맙지만 사양"이 됨
    이전 줄 끝의 세 공백 문자는 비꼼을 나타내며, 후행 공백을 쉽게 구분할 수 없는 곳에서는 문자 그대로 해석하면 됨
    • 이 실험의 요지는 Forth에는 재정의할 수 없는 문자 하나, 즉 공백이 있는데 그 제약을 없애면 어떻게 되는가로 보임
      언급한 부트스트랩 부분은 실제로 독자에게 공백과 줄바꿈을 구분자로 취급하라고 알려주는 대목임
      즉 구분자로 선언하는 구간에서 공백이 의미를 갖는다고 불평하는 셈임
      물론 그렇게 생각할 권리는 있지만, 이걸 더 잘할 방법이 있었는지는 궁금해짐
    • 그 공백 문자들은 이전에는 다른 문자와 다를 바 없던 공백을 실제로 공백이라는 것으로 만드는 방식임
      한 번은 리터럴 공백이 그런 식으로 의미를 갖지 않고는 이걸 할 방법이 떠오르지 않음
  • "어떤 형태의 문법을 갖는 함정"이라지만, 문법은 구조를 제공함
    문법 없이 "sentence this without you syntax read can" 같은 문장을 읽을 수 있다고 생각하는가?
    Cognition이 완전 후위식 반문법을 쓴다지만, 후위식도 문법임
    독일어 화자에게 문장 끝에 오는 동사에 대해 물어보면 됨
    첫 예시에서도 피연산자와 연산자의 순서가 중요하고, 그게 바로 문법임
    이건 말도 안 되게 압축된 언어를 만들려는 시도로 보이며 APL이 많이 떠오름
    저자들에게 힌트를 주자면, 문법을 없앤 게 아니라 인간이 읽고 이해하기 어렵게 만들었을 뿐이고, 가독성과 이해 가능성은 프로그래밍에서 중요한 요소임
  • 읽기가 조금 까다로웠음
    발밑의 규칙이 계속 바뀌는 느낌이라, 규칙과 단어가 도입되었다가 제멋대로 재정의되는 것 같음
    전체적으로 Numberwang 같은 분위기가 있어서 풍자처럼 받아들여지는 이유 중 하나로 보임
    또 다른 큰 이유는 부트스트래핑 단계가 우스꽝스러울 정도로 쓰였기 때문인데, 그건 의도한 듯함
    분명 깊은 무언가가 있지만, 더 진한 커피를 마신 뒤 다시 읽어봐야겠음
    • 설명할 것이 많고, 지금 설명 방식이 최적이 아니었다는 생각도 듦
      이 글의 작성자인데, 문제는 전달해야 할 내용이 정말 많다는 점임
      Matthew와 이 언어 설계를 두고 3주 동안 매일 몇 시간씩 주고받았고, 실제로 나를 모르는 사람들에게 채워 넣어야 할 맥락도 많음