ホモアイコニックな Python 言語
(aljamal.substack.com)McCarthy の "Lisp in Lisp" を Python で実装する
-
1960年代初頭に John McCarthy が開発した Lisp は、homoiconicity の特性を持っているため、コードとデータを相互に交換できる
- Lisp ではコードとデータの境界が曖昧になる
- そのため Lisp は自分自身を自然に表現できる
-
Lisp 1.5 マニュアル 13 ページ下部の半ページ分のコードは、Lisp そのものだった
- Alan Kay はこれを「ソフトウェアのマクスウェル方程式」と呼んだ
- プログラミングの世界全体が、わずか数行のコードに圧縮されている
-
これを理解するために、Python を使って "Lisp in Lisp" のコードを再実装してみるのは良い方法
- ほとんどのプログラマは Lisp の構文には慣れていないが、Python の構文には慣れているはず
- Lisp コードの精神をできるだけ保ちながら、Python で書き直すことが目標
Lisp の M-expression と S-expression
-
Lisp はもともと 2 つの構文 flavor を持っていた
- M-expression(メタ表現式): コードの flavor
- S-expression(記号表現式): データの flavor
- 両者は意味的には同一
-
"Lisp in Lisp" のコードは M-expression で書かれており、S-expression Lisp を実装している
-
Lisp の M-expression を Python のコード構造に変換し、S-expression は Python リストで表現するのが 1 つの方法
- Lisp は List Processing の略であり、リストという単一のデータ構造だけを使う
1次実装
-
Python リストの基本関数で Lisp の基本演算を実装
- atom(x): x がリストかどうかを確認
- eq(x,y): x と y が同じか確認
- car(x): リストの最初の要素を返す
- cdr(x): リストの残りの部分を返す
- cons(x,y): アトムをリストに追加
- append(x,y): 2 つのリストを結合
-
いくつかの再帰の基本要素は無視し、Llama3-70b の助けを借りれば、"Lisp in Lisp" コードのサブセットに対するインタプリタを素早く実装できる
2次実装
-
1次実装ではラムダ機能が抜けている
- ラムダは Lisp で関数を定義し呼び出す主要な方法
- ラムダがなければ再帰を実装できず、再帰がなければチューリング完全ではない
-
ラムダを実装するには assoc(x,y) と pairlis(x,y) の基本要素が必要
- assoc(x,y) は連想リストを使った key/value 辞書ルックアップ
- pairlis(x,y) は Python の zip(x,y) と同じ
-
Lisp には loop がないため、単純な線形探索にも再帰を使う必要があった
- しかし Python ではリスト内包表記を使ってエレガントに変換できる
- evcon と evlis も同様に loop に変換できる
-
eval 関数はもともと Lisp で 2 つの引数を取る
- 1 つ目は式(s-exp)、2 つ目は環境(environment)で、key/value のリスト
- 環境は LAMBDA の変数束縛を保持する
- 動的スコープ(dynamic scoping)の手法を使う
GN⁺ の意見
-
Lisp の homoiconicity 特性を Python で模倣した興味深い試み。とはいえ、Lisp 固有の特性を完全に移し替えるには限界があるように見える。Lisp の魅力を体験するなら、やはり Lisp 自体を学ぶのが最もよさそう。
-
ラムダ関数や動的スコープなど、Lisp の強力な機能を Python で実装したのは印象的。だが、実際のプロジェクトに適用するには不足している点も多そう。教育用や研究目的としては価値がありそうだ。
-
こうした試み自体が、プログラミング言語の本質について深く考えるきっかけになり得る。言語の構文や実装を離れ、プログラミングパラダイムの観点から眺める視点を持てる。
-
Lisp 系言語を学ぶことは、関数型プログラミングやメタプログラミングへの洞察を得る助けになるかもしれない。Scheme、Clojure、Racket など、現代的な Lisp 系言語を見てみるのもよい。
1件のコメント
Pythonに埋め込まれたLispの方言
https://hylang.org/