symbol-macrolet

symbol-macrolet の挙動をちゃんとわかってないことが判明したので sbcl で調べてみた。

operator は展開しない

(defun foo () 'DEFUN)
=> FOO

(symbol-macrolet ((foo 'SYMBOL-MACRO))
  (list foo (foo)))
=> (SYMBOL-MACRO DEFUN)

(symbol-macrolet ((foo 'SYMBOL-MACRO))
  (labels ((foo () 'LOCAL-FUNCTION))
    (list foo (foo))))
=> (SYMBOL-MACRO LOCAL-FUNCTION)

macro 展開で出現した symbol は展開する

(defmacro *foo () 'foo)
=> *FOO
(macroexpand '(*foo))
=> FOO

(symbol-macrolet ((foo 'SYMBOL-MACRO))
  (list foo (*foo)))
=> (SYMBOL-MACRO SYMBOL-MACRO)

shadowing された symbol は展開しない、マクロ展開で出現した symbol でも同様

(symbol-macrolet ((foo 'SM-FOO)
                  (bar 'SM-BAR))
  (let ((foo 'LEXICAL-VALUE))
    (list foo (*foo) bar)))
=> (LEXICAL-VALUE SM-BAR LEXICAL-VALUE)

tag は展開されない

(let ((c 0))
  (symbol-macrolet ((foo (print "hehehe")))
    (tagbody
      foo
      (print (incf c))
      (if (< c 3) (go foo) foo))))
1
2
3
"hehehe"
=> NIL