아서 휘트니의 C 코드를 읽으며 똑똑해지기 (2024)
(needleful.net)- Arthur Whitney가 만든 50줄짜리 K 언어 인터프리터 C 코드를 분석하며, 그의 독특한 코딩 스타일을 해석한 기록
 - 코드에는 매크로 기반의 압축 문법, 비표준 C 확장, 암묵적 인자 사용 등 일반적인 C 코드와 다른 실험적 구조가 다수 포함
 - 작성자는 각 매크로와 함수의 의미를 직접 해석하며, APL 계열 언어의 철학과 코드 밀도의 장단점을 탐구
 - 코드의 장점으로는 짧은 길이와 높은 구성력, 단점으로는 비표준 문법과 가독성 저하를 지적
 - 결론적으로, 이 코드는 “짧게 쓰는 법”보다 문제를 완전히 이해한 뒤 코드를 쓰는 사고방식의 중요성을 보여주는 사례로 평가됨
 
Arthur Whitney와 그의 코드
- Arthur Whitney는 A, K, Q 언어와 kdb, Shakti 데이터베이스를 설계한 컴퓨터 과학자
- kdb는 금융권에서 사용되는 초고속 시계열 데이터베이스, Shakti는 그보다 빠른 버전으로 1조 행 규모 데이터셋을 처리하도록 설계됨
 
 - 그의 언어들은 APL의 영향을 강하게 받은 배열 기반 언어로, 간결성과 수학적 표현력을 중시함
 - 글의 초점은 금융 응용이 아니라, 휘트니가 작성한 C 코드의 독특한 스타일을 분석하는 데 있음
 
50줄짜리 K 인터프리터의 구조
- 공개된 ksimple 리포지토리에는 휘트니가 며칠 만에 작성한 약 50줄의 C 인터프리터가 포함
 - 코드의 핵심은 
a.h와a.c두 파일로 구성되어 있으며, 매크로를 통한 함수 정의 축약과 포인터를 정수처럼 사용하는 구조가 특징 - 
typedef char*s,c;구문을 통해s를 문자열 포인터,c를 문자형으로 정의 - 
s Q=(s)128;은 포인터를 정수처럼 사용한 예로, 코드 전반에서 Q가 오류 상태를 나타내는 특수 값으로 쓰임 - 
({e;})형태의 statement expression과?:연산자 등 GCC 확장 문법이 다수 사용됨 
주요 매크로와 함수의 의미
- 
#define _(e...) ({e;}): 여러 문장을 하나의 표현식으로 묶는 매크로 - 
#define i(n,e): 반복문 축약 표현,for루프를 한 줄로 표현 - 
#define Q(e)등은 에러 처리 매크로,Qr,Qd,Qz는 각각 rank, domain, not-yet-implemented 오류를 반환 - 
_s,_i,f,F매크로는 함수 선언을 간소화하며, 암묵적으로 인자x,a를 사용 - 
ax,ix,nx등은 데이터 타입 판별 및 인덱싱 매크로,ax는 “x가 원자(atom)인지”를 판단 - 
f(w,write(1,ax?&x:x,ax?1:strlen(x));x)는 출력 함수, 원자면 문자로, 벡터면 문자열로 출력 
인터프리터의 동작 방식
- 
m(x)함수는 메모리 할당 및 길이 정보 포함 포인터 생성, 벡터의 최대 길이는 255바이트 - 
g(a,v)매크로는 원자/벡터 연산을 통합 처리,not,sub,At,_A등의 함수가 이를 기반으로 정의 - 
G(f,o)매크로는 이항 연산자 함수 자동 생성,<,==,+,*,&,|등의 연산을 지원 - 
cat,rev,cnt,Tak등은 벡터 조작 함수,rev는ind함수를 이용해 역순 인덱스를 생성 - 
e()함수는 재귀적 평가기, 문자열을 오른쪽에서 왼쪽으로 읽으며 단일 문자 변수, 숫자, 연산자를 처리 - 
main()은 입력을 받아e()로 평가 후 결과를 출력하는 REPL 루프 형태 
코드 스타일에 대한 평가
- 
장점
- 조합 가능한 매크로로 구성된 간결한 원시 연산 집합
 - 짧은 코드 길이로 인해 스크롤 없이 전체 로직을 한눈에 파악 가능
 - 고밀도 표현을 통해 코드의 논리적 구조를 압축
 
 - 
단점
- 
char*를 정수처럼 사용하는 비의미적 타입 처리 - ASCII 코드 직접 사용, 복잡한 삼항 연산자, 비표준 문법 등으로 인한 가독성 저하
 - 암묵적 인자와 짧은 변수명으로 인해 의도 파악이 어려움
 
 - 
 - 
중립적 요소
- GCC 전용 문법(
?:, statement expression)은 흥미롭지만 이식성 저하 - 암묵적 인자 사용은 소규모 코드에서는 유용하나, 대규모 코드에서는 혼란 유발 가능
 - 짧은 이름은 익숙해지면 효율적이지만, 의미 전달력은 약함
 
 - GCC 전용 문법(
 
결론과 교훈
- 이 코드는 단순히 “짧게 쓰는 법”이 아니라, 문제를 완전히 이해한 뒤 코드를 작성하는 사고방식을 보여줌
 - 휘트니의 코드는 이미 완성된 수학적 모델을 코드로 옮긴 형태, 즉 “생각을 코드로 표현한 결과물”
 - 작성자는 자신이 평소 코드 안에서 문제를 해결하려는 습관을 반성하며,
앞으로는 코드 작성 전 개념적 모델링과 사고 정리의 중요성을 강조 - 최종적으로, 이 실험은 “코드를 읽는 능력”을 단련하고, 코드 밀도와 사고 명료성의 균형을 탐구한 경험으로 정리됨
 
향후 실험 아이디어
- 인터프리터 확장 실습 제안:
- 부동소수점 벡터 지원
 - 255개 이상 원소 처리
 - 다자리 숫자 및 변수명
 - 배열 리터럴과 공백 무시
 - 메모리 관리 및 오류 표시 기능 추가
 - 미구현 함수 완성
 
 - 이러한 확장은 휘트니식 코드 스타일을 유지하면서 실제 사용 가능한 언어로 발전시키는 실험이 될 수 있음
 
Hacker News 의견
- 
이 코드의 매크로들은 공통 연산을 압축하기 위한 것임
나는 J Incunabulum을 먼저 읽고 나서 이 코드를 봤는데, C에 익숙한 프로그래머들이 중간부터 읽기 시작하면 초반의 매크로 정의들이 혼란을 줄 수 있음
매크로들이 서로를 기반으로 쌓이기 때문에 코드가 빠르게 추상화의 사다리를 오름
특히Iterate매크로(i)가 마음에 드는데, 장황한 루프를 한 글자로 줄여줌
이런 밀도 높은 코드가 읽기 어려운 이유는, 수십 줄 안에 수많은 추상화를 만들고 바로 사용하는 방식 때문임
그래서 한 글자씩 천천히 읽어야 함
수백 개의 얇은 파일로 구성된 대규모 코드베이스에서 일해본 입장에서는, 이런 극단적인 압축성이 오히려 신선하게 느껴짐- 나도 Incunabulum을 읽고 비슷한 생각을 했지만, 변수 이름을 이모지로 바꿔보니 훨씬 이해가 쉬워졌음
이모지 버전 코드 이미지를 보면 알 수 있듯, 문제의 일부는 정보 밀도뿐 아니라 문자 형태(orthography) 에 있음
현대 언어들은 식별자에 기호나 이모지를 쓰지 못하게 하는데, 이런 시각적 구분이 가능했다면 훨씬 읽기 쉬웠을 것임
또 대부분의 에디터가 구문별 색상(syntax highlighting)을 쓰지만, 토큰 기반 색상(각 식별자마다 고유 색상)이 더 유용할 때가 많음
Sublime Text의 “hashed syntax highlighting”이 그 예임
이렇게 바꾸니 코드의 구조가 한눈에 들어왔음 - 개발자들이 오히려 거대한 코드베이스를 선호하는 것 같음
나는 하위 디렉터리 없이grep *.[ch]로 바로 찾을 수 있는 구조를 좋아함
Java 프로젝트는 특히 작은 파일이 너무 많고 내용이 빈약해서 찾기가 힘듦
IDE가 있으면 낫겠지만 나는 안 씀
Whitney는 인터뷰에서 모든 코드를 한 페이지에 담고 싶다고 했고, 그의 “IDE”는 Windows 콘솔과 Notepad라고 함 
 - 나도 Incunabulum을 읽고 비슷한 생각을 했지만, 변수 이름을 이모지로 바꿔보니 훨씬 이해가 쉬워졌음
 - 
Arthur Whitney의 C 코드를 이해하려면 먼저 APL 계열 언어를 배워야 함
그렇지 않으면 단순히 이상한 C 스타일로 보일 뿐임
Whitney는 C를 APL처럼 쓰려는 것임
공백이 없고, 한 글자 이름을 쓰며, 한 줄 함수로 구성된 스타일은 APL에서도 동일함
Pascal 프로그래머가#define begin {같은 걸 쓰는 것과 비슷하지만, Whitney는 그보다 훨씬 독창적임- APL 사용자 입장에서도 이건 이상하게 보임
Whitney가 만든 K 언어는 이런 스타일을 쓰지만, 한 줄 함수는 전통적인 APL에서는 불가능했음
매크로나 삼항 연산자, 암묵적 변수명 같은 건 APL에 없음
APL의 본질은 불변 배열 연산인데, Whitney의 C 스타일은 그 철학과는 다름 - “Pascal 프로그래머가 C로 넘어와서 
#define begin {하는 것 같다”는 말에 대해, “아, Stephen Bourne처럼 말이지”라고 농담함 - 처음엔 함수형 언어처럼 보였는데, 곧 C 전처리기의 공포를 떠올리게 됨
 - 이미 글의 서두에서 “Whitney의 C는 APL에서 영감을 받았다”고 설명하고 있음
단순 요약 댓글이 많다는 지적임 - J를 배우는 것도 괜찮을 것 같음
APL보다 접근성이 높고, 일반 키보드로 입력 가능한 기호를 쓰기 때문임 
 - APL 사용자 입장에서도 이건 이상하게 보임
 - 
Shakti를 찾아보다가 Wikipedia 링크가
k.nyc로 리디렉션되는 걸 봤는데, 페이지에는 ‘k’ 한 글자만 있음
소스를 보니 정말<div>k</div>뿐이었음
이건 HTML 버전의 Whitney식 미니멀리즘 같음 — 불필요한 건 모두 제거하고, 컴파일러가 암묵적으로 처리하도록 맡긴 느낌임- k
 
 - 
이 블로그 글은 Whitney의 코딩 스타일에 대한 평가와 상관없이 훌륭한 분석글임
작성자가 8시간 만에 쓴 것치고는 깊이가 있고, 결론 부분이 특히 인상적이었음
원문 링크 - 
Stephen Bourne이 C를 Algol처럼 만들려던 시도가 떠오름
mac.h 예시와
expand.c 예시를 보면 비슷한 감성이 느껴짐 - 
모든 분야에는 “best practice”가 있지만, 그건 평균적인 경우에만 잘 맞음
특정 상황에서는 오히려 반대로 가는 게 더 나을 때도 있음
결국 집단 지혜는 기본값으로 삼되, 스스로 생각하기 시작하면 그 틈이 보이기 마련임- 그래서 “best practice”라는 표현이 싫음
사실은 평균적인 수준의 절충안일 뿐임
효율성과 성능을 희생하고 유지보수성과 일관성을 얻는 거래임 - 좋은 제품을 만드는 것과 코드베이스의 가독성이나 학습 곡선은 별개임
한쪽이 잘된다고 해서 다른 쪽도 자동으로 따라오는 건 아님 
 - 그래서 “best practice”라는 표현이 싫음
 - 
코드에 대해 공격적으로 굴지 않고 균형 잡힌 시각을 보여줘서 좋았음
재미있게 읽었고, 나중에 다시 읽어볼 생각임 - 
이런 코딩 스타일이 특정 패러다임인지 궁금했음
실제 프로젝트에서 이런 코드를 본 적은 거의 없고, “business card ray tracer” 같은 예외만 있음
Whitney가 만든 J 언어의 소스 코드도 비슷하게 극도로 압축된 스타일을 가짐- 맞음, 이건 Whitney의 고유한 코딩 스타일임
그의 배열 언어 인터프리터들에서 일관되게 쓰이며, 몇 페이지 안에 전체 구현을 담는 것으로 유명함
관련된 HN 논의들을 모아둔 메타 댓글 링크도 있음 - “이런 코드를 실제로 본 적 없다”는 말에, “운이 좋았음”이라고 답함
이건 더 이상 C가 아니라, C 위에 새로 만든 내부 DSL 같은 언어임
C는 단지 첫 번째 컴파일 타깃일 뿐임 - J, K 같은 APL 계열 언어와 유사함
비ASCII 기호를 쓰고, 극단적인 밀도로 많은 정보를 한 페이지에 담을 수 있음
익숙해지면 추상화 계층이 줄어드는 장점도 있음 - 비슷한 접근으로 만든 co-dfns 관련 영상도 있음
C는 아니지만 비슷하게 고밀도 스타일로 작성됨 - 농담처럼 “이건 OCC(Obfuscated C Code)”라고 부름
 
 - 맞음, 이건 Whitney의 고유한 코딩 스타일임
 - 
다음 매크로 정의들을 보면
#define _(e...) ({e;}) #define x(a,e...) _(s x=a;e) #define $(a,b) if(a)b;else #define i(n,e) {int $n=n;int i=0;for(;i<$n;++i){e;}}이런 식으로 공통 연산을 압축하는 매크로들이지만, 너무 과감해서 “** 전쟁 범죄급 코드**”라고 농담함
- 일부 매크로는 문법적으로도 잘못됨
예를 들어#define $(a,b) if(a)b;else는 괄호가 없어 버그 유발 가능성이 큼
단순히 게으른 작성임 
 - 일부 매크로는 문법적으로도 잘못됨
 - 
이런 매크로 사용은 좋은 예라고 생각함
겉보기엔 무섭지만, 사실 간결한 선언형 C 스타일임
다만 밀도가 높고, 생소한 매크로 문법 때문에 읽기 어렵게 느껴질 뿐임
“oo”는 아마 무한대 오류 상태나 디버그용 출력일 가능성이 있음- 나도 이런 매크로들이 유용하다고 생각함
DO(n, code)같은 간단한 반복문 매크로가 있으면 좋겠음
작은 연산 단위(예: opcode, forth word, APL 연산자)를 한 줄로 표현하면 전체 구조를 한눈에 볼 수 있음
코드의 ‘사이 공간’ 에서 의미를 읽는 게 중요하다고 느낌 - “좋은 매크로 사용”이라는 말에 단호히 “아니오”라고 반박함
 
 - 나도 이런 매크로들이 유용하다고 생각함