私の静的に型付けされたスクリプト言語Umkaの開発は、数十行のスクリプトよりも複雑な例を使用して言語機能をテストする必要があった段階に入りました。このために、Lispインタープリターを自分の言語で実装することにしました。 Go言語の作成者の1人であるRobPikeによる教育実験に触発されました。 Pikeは最近、Goで小さなLispインタープリターを公開しました。通訳の説明が古代のLisp1.5マニュアルの13ページにあるというPikeの発言に特に感銘を受けました。..。 UmkaとGoの構文上の親和性を考えると、文字通りPikeのコードを転送するのではなく、完全にゼロから、Umkaでそのようなインタープリターを構築する誘惑に抵抗することは困難でした。 Lispと機能言語の愛好家が私に美しさと接触しているという素朴な驚きを許してくれることを願っています。
初心者にとって、Lispはショックに近いものに出くわす可能性があります。コードとデータの境界線はどこにありますか?ループはどこにありますか?スタックはどこにありますか?唯一のデータ構造はツリーです。リストを表すこともできます。また、プログラムが解析されると、抽象的な構文ツリーになります。また、式を評価するときにスタックを置き換えます。任意のツリーをコードとして実行したり、データとして使用したりすることができます。ループの代わりに-再帰。言語の中核には算術さえありません。それでも、それは無限に拡張され、構文上の砂糖を振りかけることができるチューリングの完全な言語です。
最小限のLispインタープリターを定義すると、実際には1ページもかかりません。もちろん、一気に:前のいくつかのページで定義された関数を使用します。Lispの作成者であるJohnMcCarthyは、簡潔に自分を凌駕し、最終的には言語定義と通訳ソースを含むLispマイクロマニュアルを公開したようです。合計2ページの雑誌です。確かに、彼は見出しに「真実全体ではない」と付け加えた。
言語のコア(ここでは最も古くて最も単純な方言について話している)には、5つの基本関数、4つのキーワード、および言語自体では表現できない2つの定数が必要です。
それらに精通していない人のための基本的な言語構造
(car x)
-リストの先頭を強調表示x
(cdr x)
—x
(cons x y)
—x
y
(atom x)
—x
(eq x y)
—x
y
(cond (a x) (b y))
—x
y
a
b
(quote x)
—x
,((lambda (x) a) y)
—a
,x
y
((label ff (lambda (x) a)) y)
—ff
t
—nil
—
, . , , , 6:
((label fac (lambda (n) (cond ((eq n 0) 1) ((quote t) (mul n (fac (sub n 1))))))) 6)
Lisp, . Lisp 1.5 13 , . . , REPL . , , , label
defn
, , . Lisp .
インタプリタ全体が再帰とツリー処理に満ちているため、スタッキングからガベージコレクションまで、Umka言語の多くの機能の優れたテストとして機能しました。Umkaはテストでうまくいったと思います。名前と高度な型宣言のエクスポートに関連する2つまたは3つのマイナーなバグを修正する必要がありました。インタプリタコード全体の長さは400行未満でした。
私の通訳と遊んで、リレーを介してロブパイクからのインスピレーションを伝えたい人には、最新リリースからではなく、マスターブランチからの例を含むフォルダーを取得することをお勧めします。