マクロの展開結果のgensymを通常のシンボルに置き換える - lisp-cookbook-ja/common-lisp GitHub Wiki
大きな展開結果のマクロをデバッグする場合、展開結果の全体や一部を直接実行したいことがあります。
しかし、展開結果にgensymが混っていると色々と厄介です。
この様な場合、print-gensymをnilにすることにより結果から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)))"
- print-gensymを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))