- 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 の2ファイルで構成され、マクロによる関数定義の省略記法 と ポインタを整数のように扱う構造 が特徴
typedef char*s,c; 構文によって s を文字列ポインタ、c を文字型として定義
s Q=(s)128; はポインタを整数のように使った例で、コード全体で Qがエラー状態を表す特別な値 として使われる
({e;}) 形式の statement expression や ?: 演算子など、GCC拡張構文 が多数使われている
主なマクロと関数の意味
#define _(e...) ({e;}) : 複数の文を1つの式にまとめるマクロ
#define i(n,e) : 反復処理の省略表現で、for ループを1行で表す
#define Q(e) などは エラー処理マクロ で、Qr、Qd、Qz はそれぞれ rank、domain、not-yet-implemented エラーを返す
_s、_i、f、F マクロは 関数宣言を簡素化 し、暗黙的に引数 x、a を利用する
ax、ix、nx などは データ型判定およびインデクシング用マクロ で、ax は「xがアトムかどうか」を判定する
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() 関数は 再帰的評価器 で、文字列を右から左へ読みながら 1文字の変数、数字、演算子 を処理する
main() は入力を受け取り、e() で評価した後に結果を出力する REPLループ の形を取る
コードスタイルの評価
- 長所
- 組み合わせ可能なマクロ で構成された 簡潔な原始演算の集合
- 短いコード長 により、スクロールなしでロジック全体を一望できる
- 高密度な表現 によってコードの論理構造を圧縮している
- 短所
char* を整数のように扱う 意味論に乏しい型処理
- ASCIIコードの直接使用、複雑な三項演算子、非標準構文 などによる可読性の低下
- 暗黙の引数 と 短い変数名 によって意図を把握しにくい
- 中立的な要素
- GCC専用構文(
?:、statement expression)は興味深いが、移植性を損なう
- 暗黙の引数利用 は小規模コードでは有用だが、大規模コードでは混乱を招く可能性がある
- 短い名前 は慣れれば効率的だが、意味を伝える力は弱い
結論と教訓
- このコードは単に「短く書く方法」ではなく、問題を完全に理解したうえでコードを書く思考法 を示している
- ホイットニーのコードは すでに完成した数学的モデルをコードへ写した形、つまり「思考をコードで表現した結果物」だといえる
- 筆者は自分が普段 コードの中で問題を解こうとする癖 を反省し、
今後は コードを書く前の概念的モデリングと思考整理の重要性 を強調している
- 最終的に、この実験は「コードを読む力」を鍛え、コード密度と思考の明晰さのバランス を探る経験としてまとめられている
今後の実験アイデア
- インタプリタ拡張の提案:
- 浮動小数点ベクタのサポート
- 255個を超える要素の処理
- 複数桁の数字と変数名
- 配列リテラルと空白の無視
- メモリ管理とエラー表示機能の追加
- 未実装関数の完成
- こうした拡張は、ホイットニー流のコードスタイルを保ちながら 実用可能な言語へ発展させる実験 になりうる
1件のコメント
Hacker Newsの意見
このコードのマクロは、共通の操作を圧縮するためのもの 私は先に J Incunabulum を読んでからこのコードを見たが、C に慣れたプログラマが途中から読み始めると、冒頭のマクロ定義に戸惑うかもしれない マクロが相互に積み上がっていくので、コードはすぐに抽象化のはしごを登っていく 特に
Iterateマクロ(i)が気に入っていて、冗長なループを1文字に縮めてくれる こうした高密度なコードが読みにくいのは、数十行の中で大量の抽象化を作ってすぐ使う書き方だからだ だから1文字ずつゆっくり読む必要がある 数百の薄いファイルで構成された巨大コードベースで働いた経験からすると、こういう極端な圧縮性はむしろ新鮮に感じるgrep *.[ch]としてすぐ探せる構造が好きだ Java プロジェクトは特に小さいファイルが多すぎて中身も薄く、探しにくい IDE があればましだろうが、私は使わない Whitney はインタビューで、すべてのコードを1ページに収めたいと言っていて、彼の「IDE」はWindows コンソールと NotepadだというArthur Whitney の C コードを理解するには、まずAPL 系言語を学ぶ必要がある そうでないと、単に奇妙な C スタイルにしか見えない Whitney は C を APL のように使おうとしているのだ 空白がなく、1文字の名前を使い、1行関数で構成されるスタイルは APL でも同じだ Pascal プログラマが
#define begin {のようなことをするのに似ているが、Whitney はそれよりはるかに独創的だ#define begin {をやるみたいだ」という発言に対して、「ああ、Stephen Bourne みたいにね」と冗談を言っているShakti を調べていたら、Wikipedia リンクが
k.nycにリダイレクトされ、ページには**「k」の1文字だけ**があった ソースを見ると本当に `k` しかなかった これは HTML 版のWhitney 流ミニマリズムのようだ。不要なものをすべて取り除き、コンパイラが暗黙に処理してくれることに任せている感じだ
k
このブログ記事は、Whitney のコーディングスタイルをどう評価するかとは別に、すばらしい分析記事だ 著者が8時間で書いたにしては深みがあり、結論部分が特に印象的だった 原文リンク
Stephen Bourne が C をAlgol のようにしようとした試みを思い出す mac.h の例と expand.c の例を見ると、似た感覚がある
どの分野にも「best practice」はあるが、それは平均的なケースにしかうまく当てはまらない 特定の状況では、むしろ逆へ進む方がよいこともある 結局、集合知はデフォルトとして採用しつつも、自分で考え始めればその隙間が見えてくるものだ
コードを攻撃的に扱わず、バランスの取れた視点を見せてくれたのがよかった 楽しく読めたし、あとでまた読み返そうと思う
こういうコーディングスタイルが特定のパラダイムなのか気になっていた 実際のプロジェクトでこういうコードを見たことはほとんどなく、「business card ray tracer」のような例外があるくらいだ Whitney が作った J 言語の ソースコード も同様に極端に圧縮されたスタイルを持っている
次のマクロ定義を見ると