ダイナミックスコープをレキシカルスコープに直す。
2016年に作った Lisp (Scheme) インタプリタ、ダイナミックスコープだったまま放置していたのでレキシカルスコープに直した。
ダイナミックスコープとレキシカルスコープとは。
スコープの変数の参照のやり方の違い。
例を挙げると
(define x 123) (define (f) x) (let ((x 456)) (print (f)))
のようなコードでは、ダイナミックスコープでは 456 、レキシカルスコープでは 123 である。
大体の言語はレキシカルスコープで実装されている。わかりやすいので。
どうしてダイナミックスコープで実装してしまったか。
実行時の関数呼び出しを評価する際になって初めて環境オブジェクトを生成していた。よって外側の参照を行う際、呼び出し元の環境を遡って参照する=ダイナミックスコープになっていた。
kantele/eval.js at d85caa71fb5206f93b0912b9582e07f3bdb2003c · 45deg/kantele · GitHub
修正
関数(あるいはスコープ)が作られる際に環境を埋め込む。いわゆるクロージャを作る。 完全なインタプリタ型で実装していたので思ったよりかなり楽に実装できた(関数オブジェクトのコンストラクタの引数に加えるだけ) *1
Fixed: dynamic scope -> lexical scope · 45deg/kantele@966ec24 · GitHub