- Common Lispの「らしさ」を体感するには、実際にうまく書かれたコードを読むのが近道です。
- テキストアドベンチャーやレイトレーサーは100〜500行と短く、基本イディオムや関数型スタイルを把握できます。
- ミニLispインタプリタはevalとapplyの構造を、マクロDSLはコードを生成するコードの仕組みを学べます。
- Lispらしさを直接感じたいならインタプリタとマクロDSL、読み切る体験を積むならアドベンチャーとレイトレーサーが向いています。
1. 1. テキストアドベンチャー(100〜300行)
Lispのチュートリアルをひと通りこなしても、「Lispらしい」コードがどういうものか、まだピンとこないものです。
そこで、うまく書かれた実装を読んでみることにしました。
『Land of Lisp』に収録されているテキストアドベンチャーが典型例です1。
ゲームの状態をリストで表し、コマンドをパターンマッチで処理する構造で、全体像を掴みやすく、入門として読みやすい題材です。defstruct や defparameter でデータを定義し、cond や case でコマンドを分岐させる流れは、Common Lispの基本的なイディオムをひと通り見渡せます。
ちなみに、Emacs付属の dunnet も同じジャンルで、実用ソフトウェアの文脈でどう書かれているかを確認できます2。
2. 2. レイトレーサー(200〜500行)
ベクトル計算・交差判定・再帰の三つが中心になります。
再帰は反射の処理に使われます。
アルゴリズム自体は数学的ですが、プログラムの構造は素直です。
関数を組み合わせてシーンを組み立て、再帰で光線の反射をたどる流れが、関数型スタイルと自然に合致しています。
実行すると画像が出力されるので、コードの変更が結果に即座に反映され、挙動を確かめながら読み進められます。
Common Lispの実装は200〜300行に収まるものが多く、読み通すのに現実的なボリュームです。
3. 3. ミニLispインタプリタ(150〜400行)
いわゆるメタ循環インタプリタ、つまり「LispでLispを書く」実装です。
代表的な教材は『SICP(Structure and Interpretation of Computer Programs)』第4章のevaluatorです3。
構造は read、eval、apply の三関数に集約されます。
それぞれS式を読む、評価する、関数を適用するという役割で、この三つで一つの言語が成立します。
そこが読んでいて一番の発見になります。
環境のチェーンをどう扱うかが読解の鍵になります。
ちなみに、Lispインタープリタを作る実装では、Pythonを使ったPeter Norvigの lis.py も132行と構造が明快で、これ先に読んでから Common Lisp版を読むのもよいかもしれません4。
4. 4. マクロDSL(200〜800行)
DSLとはある用途に特化した小さな言語のことで、HTMLを生成するものやSQLを組み立てるものをマクロで実装する例があります。
Common Lispの最大の特徴であるマクロが全面に出るテーマです。
コードを書くコードを追うことになるので最初は混乱しますが、macroexpand でマクロが展開されたあとの形を確認しながら読むと理解が進みます。
(defmacro when (cond &body body)
`(if ,cond (progn ,@body)))Code language: CSS (css)
まずは、単純なものから始めて、パターンマッチングの実装へ進む順序が読みやすいです。
5. 5. AI研究コード(数千行〜)
Lisp文化との関わりが深い題材で、1980年代の研究プロジェクトに端を発します。
Lispがどういう問題領域で使われてきたかを知りたいなら、読む価値があります。
Euriskoは経験則であるヒューリスティックを自分で生成・変更するAIシステムで、Douglas Lenatが開発しました5。
Copycatは類推による認知モデルの実装です6。
どちらも大規模で入門には向きませんが、コードの思想を追うのが主な目的になります。
6. まとめ
| テーマ | 規模 | 得られるもの |
|---|---|---|
| テキストアドベンチャー | 0〜300行 | 基本イディオム |
| レイトレーサー | 0〜500行 | 関数型スタイル |
| ミニインタプリタ | 0〜400行 | evalとapplyの構造 |
| マクロDSL | 0〜800行 | マクロとメタプログラミング |
| AI研究コード | 数千行〜 | 思想と歴史 |
「Lispらしさ」を体感したいなら、インタプリタとマクロDSLが最も直接的です。
テキストアドベンチャーとレイトレーサーは、コード全体をひと通り読み切る体験を積むのに向いています。
いずれも100〜500行の範囲に収まり、週末に読み切れるボリュームです。
- Conrad Barski著、No Starch Press刊(2010年)。コミックを交えながらCommon Lispをゲーム作成で学ぶスタイルで知られる。 – Land of Lisp – No Starch Press
- Ron Schnellが1982年にMaclispで書いたゲームをEmacs Lispに移植したもの。1994年からGNU Emacsに同梱されており、
M-x dunnetまたはemacs -batch -l dunnetで起動できる。 – Dunnet (video game) – Wikipedia - Harold AbelsonとGerald Jay Sussmanによる教科書。MITのCS入門講義で1984年から2007年まで使われた。全文がCC BY-SA 4.0ライセンスで無料公開されている。 – SICP – MIT Press
- 132行のPythonでSchemeのサブセットを実装したインタプリタ。元Google Research責任者のNorvig本人が解説ページを公開している。 – How to Write a (Lisp) Interpreter (in Python) – norvig.com
- 開発はCarnegie Mellonで1976年に開始、Stanford大学で継続。Lenatは生前ソースコードを非公開にしていたが、2023年の死後にStanford AILアーカイブから発見・公開された。 – Eurisko – Wikipedia
- Douglas HofstadterとMelanie Mitchellが1988年にCommon Lispで開発した。現在のオリジナルコードはLucid Common Lispの旧グラフィックライブラリに依存しており動作しないが、PythonやJavaへの移植版がある。 – Copycat (software) – Wikipedia