symbol-macrolet 内で macrolet したら(sbcl にて)
(symbol-macrolet ((foo (+ 1 2 3))) (macrolet ((foo () `,foo)) (list foo (foo)))) => (6 30) (symbol-macrolet ((foo :symbol-macro)) (macrolet ((foo (foo) `(list ,foo foo))) (foo :local-macro-arg))) => (:LOCAL-MACRO-ARG :SYMBOL-MACRO)
ふむ
(symbol-macrolet ((foo :SYMBOL-MACRO)) (macrolet ((bar (arg) `(list ,foo ,arg))) (bar :MACRO-ARG))) => (:SYMBOL-MACRO :MACRO-ARG) (symbol-macrolet ((foo :SYMBOL-MACRO)) (macrolet ((bar (arg) `(list foo ,arg))) (bar :MACRO-ARG))) => (:SYMBOL-MACRO :MACRO-ARG)
symbol-macro foo は macro bar の展開時でも展開後でも expansion :SYMBOL-MACRO に展開される、と。
;; これは xyzzy (macroexpand '`(list foo ,arg)) => (list 'list 'foo arg) (macroexpand '`(list ,foo ,arg)) => (list 'list foo arg)
えーと、macrolet のマクロ定義部分で symbol-macrolet を展開しても 'foo は symbol-macro 展開しないのでそのままになる。でも macro 展開されると foo になって symbol-macro 展開はしなきゃダメって話に。
(defmacro get-env (&environment env) `,env) => GET-ENV (macrolet ((foo () :EXPANSION)) (macroexpand '(foo) (get-env))) => :EXPANSION => T (symbol-macrolet ((foo :SM-FOO)) (macrolet ((foo (foo) `(list ,foo foo))) (macroexpand '(foo :ARG) (get-env)))) => (LIST :ARG FOO) => T (symbol-macrolet ((foo :SYMBOL-MACRO)) (macrolet ((foo (foo) `(list ,foo foo))) (foo :MACRO-ARG))) => (:MACRO-ARG :SYMBOL-MACRO)
(少なくとも sbcl では)先に macrolet で定義されたローカルマクロを展開して、その後(ローカルマクロの展開形)に含まれる symbol-macro を展開するようだ。
(macrolet ((NAME ARG MACRO-DEF) ...) BODY...)
- MACRO-DEF 部分では symbol-macro 有効、ARG が shadowing される
- BODY 部分はふつーに symbol-macro 有効
- MACRO-DEF 内の symbol-macrolet を展開
- BODY 内の ローカルマクロ NAME 呼び出しを展開
- expansion に含まれる symbol-macro が展開
- 乙
ふーむ・・・。