symbol-macrolet と lexical scope
symbol-macrolet lexically establishes expansion functions for each of the symbol macros named by symbols.
symbol-macrolet は、symbols で命名された symbol-macro を展開する機能を、レキシカルに確立します。
CLHS: Special Operator SYMBOL-MACROLET
The use of symbol-macrolet can be shadowed by let. In other words, symbol-macrolet only substitutes for occurrences of symbol that would be in the scope of a lexical binding of symbol surrounding the forms.
symbol-macrolet の使用は let により隠匿されます。つまり、symbol-macrolet は forms を包む lexical なスコープ内に出現するシンボルのみを置き換えます。
CLHS: Special Operator SYMBOL-MACROLET
つまりー
(symbol-macrolet ((foo '(my name is "FOO"))) (let ((foo '(i am not "FOO"))) ;しない foo)) ;しない
だけじゃなくって、こいつらも除外しなきゃダメってこと。
(symbol-macrolet ((foo '(my name is "FOO"))) (mapcar (lambda (foo) ;しない foo) ;しない foo)) ;する (symbol-macrolet ((foo '(my name is "FOO"))) (multiple-value-bind (foo bar baz) ;しない (values-list foo) ;する (list foo bar baz 'not "FOO"))) ;しない (symbol-macrolet ((foo '(my name is "FOO"))) (do ((foo foo (cdr foo))) ;しない する しない ((endp foo)) ;しない (print foo))) ;しない (symbol-macrolet ((foo '(my name is "FOO"))) (with-gensyms (foo bar baz) ;しない (list foo bar baz))) ;しない (symbol-macrolet ((foo #S(hoge foo '(my name is "FOO") bar 8 baz :baz?))) (with-struct (hoge- foo bar baz) ;しない foo ;する (list foo bar baz))) ;しない
くっそう。めんどいなぁ。
どんな forms だろうと、macroexpand すれば essential な forms になって、そのうちいくつかの operator が lexical scope を作るんで、そいつらについて「この operator の form はこことこことここは除外」みたいにすればいける。
symbol-macro の展開形が macro 呼び出しを含んでても、それは symbol-macrolet の読み込み時に展開されてるはずなんで無視していいはず。そうでなくても symbol-macrolet の展開(=forms の置換)後でも macro は展開されるはず。
ふーむ。