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 は展開されるはず。

ふーむ。