Deno(v1.25.0)でMake a Lispした

過去2回ぐらい挫折していたMake a Lispをカンニングも辞さない勢いでやりきった。

実装するLisp方言は、Clojureっぽい構文を採用したMalというもの。
リポジトリはこれ。最近会社でやたらとTypeScriptを触っているので & 流行っているらしいので、Denoを使用した。
Deno自体の感想は浅い使い方しかしてないので、「七面倒くさいtsconfigとか書かなくてええな」というかんじ。

Step 0: The REPL

空っぽのインターフェイスを書くだけ。終わり。

Step 1: Read and Print

字句解析と構文解析。一番カンニングした章だった。

Step 2: Eval

抽象構文木を深さ優先でひたすらevaる。
ここから先はガイドを読んどけば詰まることはない(かもしれない)。

Step 3: Environments

例のごとく変数と値のセットを記録するデータ構造を作る。
あとついでに特殊形式のdef!, let*を導入。

Step 4: If Fn Do

特殊形式を追加。とくに言う事なし。

Step 5: Tail call optimization

末尾再帰最適化。適当に再帰しとけばよかったので単純かつ美しかったおれたちのeval関数が、無惨な姿となる。
あと普通に難しい。

Step 6: Files, Mutation, and Evil

一般LispのatomとClojureのatomがまったく別の概念だということがわかる章。
ここまでデフォルトイミュータブルだったが、参照経由で値を再代入することが可能となる。

Step 7: Quoting

quotequasiquote。はちゃめちゃにむずい。
わかりやすい解説はお気楽xx入門の人のページとかかなあ。

Step 8: Macros

Lispのマクロって構文木をコードからいじれるって程度の理解だったが、

In this step you will be able to mark mal functions as macros which can manipulate mal code before it is evaluated. In other words, macros are user-defined special forms.

って説明でしっくりきた。

Step 9: Try

いがいと実装がむずい。

Step A: Metadata, Self-hosting and Interop

セルフホスティング。
エラーメッセージが想定と微妙に違ったりファイルパスを修正するのがめんどいので、この章はあまり真面目にやっていない。

雑な感想

  • なんとなくわかってはいたが、代数的データ型 & パターンマッチのない言語で言語処理系つくるのはマゾ行為ということを確信した。
  • vector型いる?conjで違う動作をすることくらいしかlist型との差異がなかったような。
  • meta-dataってなんじゃこりゃ。あほのおれには使い所がさっぱりわからん。Next StepsにErrors with line numbers and/or stack traces.とかあるから、それで使うとか?