メタレベル

先日は once-only を Scheme (R6RS) で書いた。
id:SaitoAtsushi:20100503:1272845358
しかし、 import 節に誤りが有る。 defmacro と gensym を利用するにあたって、以下のように for キーワードでメタレベルを指定しなければならない。

(import (rnrs)
        (for (defmacro) expand run))

より厳密に書くならこうだろう。

(import (rnrs)
        (for (only (defmacro) defmacro) run)
        (for (only (defmacro) gensym) expand))

Lisp 系言語はマクロ展開の段階で Lisp のコードが走ることがある。 どのタイミングで定義が行なわれるのかの記述が必要なのだ。 CommonLisp では eval-when とか言うフォームでタイミングを指定できるそうだが、 Scheme (R6RS) では展開のタイミングを「フェイズ」や「メタレベル」の概念で切り分け、 import 節で for キーワードを使って指定するようになっている。
私が主に使っている Petite Chez Scheme を含むいくつかの R6RS 処理系では指定しなくても動いてしまうのであまり考えたことがなかったが、このあたりの理屈は結構ややこしい。 イマイチ理解できた気がしない。
Document ID: 8293f650ec09198f163e01b952e6fd2b