マクロの展開結果のgensymを通常のシンボルに置き換える - lisp-cookbook-ja/common-lisp GitHub Wiki

大きな展開結果のマクロをデバッグする場合、展開結果の全体や一部を直接実行したいことがあります。

しかし、展開結果にgensymが混っていると色々と厄介です。

この様な場合、print-gensymnilにすることにより結果からgensymの#:を取り除くことが可能です。

(ただし、シンボルそのものを置き換えるわけではなく、印字表現を得るのみです)

(prin1-to-string
 (macroexpand '(loop :repeat 100 :do (print 'hello))))
;=>  "(BLOCK NIL
;      (LET ((#:LOOP-REPEAT-3100 (CEILING 100)))
;        (DECLARE (TYPE INTEGER #:LOOP-REPEAT-3100))
;        (SB-LOOP::LOOP-BODY NIL
;                            ((IF (<= #:LOOP-REPEAT-3100 0)
;                                 (GO SB-LOOP::END-LOOP)
;                                 (DECF #:LOOP-REPEAT-3100)))
;                            ((PRINT 'HELLO))
;                            ((IF (<= #:LOOP-REPEAT-3100 0)
;                                 (GO SB-LOOP::END-LOOP)
;                                 (DECF #:LOOP-REPEAT-3100)))
;                            NIL)))"
(let ((*print-gensym* nil))
  (prin1-to-string (macroexpand '(loop :repeat 100 :do (print 'hello)))))
;=>  "(BLOCK NIL
;      (LET ((LOOP-REPEAT-3099 (CEILING 100)))
;        (DECLARE (TYPE INTEGER LOOP-REPEAT-3099))
;        (SB-LOOP::LOOP-BODY NIL
;                            ((IF (<= LOOP-REPEAT-3099 0)
;                                 (GO SB-LOOP::END-LOOP)
;                                 (DECF LOOP-REPEAT-3099)))
;                            ((PRINT 'HELLO))
;                            ((IF (<= LOOP-REPEAT-3099 0)
;                                 (GO SB-LOOP::END-LOOP)
;                                 (DECF LOOP-REPEAT-3099)))
;                            NIL)))"

slime/swankでの応用

swankでは、swank::macroexpand-printer-bindings で印字時に束縛する変数を指定できますのでこれを利用して"#:"が印字されない展開結果を表示するコマンドも作れるでしょう。

(defun swank-macroexpand-all/no-gensym (form)
  (let ((swank::*macroexpand-printer-bindings*
         (cons '(*print-gensym*)
               swank::*macroexpand-printer-bindings* ) ))
    (swank:swank-macroexpand-all form) ))
;;; emacs
(defun slime-macroexpand-all/no-gensym ()
  (interactive)
  (slime-eval-macroexpand 'swank-macroexpand-all/no-gensym))