短いマクロ定義でシンボル補足を避けるための簡単な方法
シンボル補足を避けるためにたまに使う方法。
uninternされたシンボルとリードマクロのラベル付け/参照機能を併用。
;; uninternされたシンボル ;; 印字名が同じでも実体は異なるので、衝突は起きない (eq '#:var '#:var) --> NIL ;; #n=および#n#構文を使えば、複数箇所から参照可能 (eq '#1=#:var '#1#) --> T
;;;; ;; 「On Lisp」第九章から引用(シンボル補足の例) ;; startからstopまでの値をvarに束縛してbodyの実行を繰り返す (defmacro for ((var start stop) &body body) `(do ((,var ,start (1+ ,var)) (limit ,stop)) ((> ,var limit)) ,@body)) (for (x 1 5) (print x)) 1 2 3 4 5 --> NIL ;; マクロの使用者がlimitシンボルにアクセスが可能 (for (x 1 5) (setf limit 0) (print x)) 1 --> NIL ;;;; ;; 修正版 (defmacro for ((var start stop) &body body) `(do ((,var ,start (1+ ,var)) (#1=#:limit ,stop)) ; limitをuninternされたシンボルに変更 ((> ,var #1#)) ,@body)) (for (x 1 5) (print x)) 1 2 3 4 5 --> NIL ;; マクロの使用者はマクロ内で使われている#:limitシンボルへのアクセスは不可能 (for (x 1 5) (setf #:limit 0) (print x)) ; (SETF #:LIMIT 0) ; ==> ; (SETQ #:LIMIT 0) ; ; caught WARNING: ; undefined variable: #:LIMIT ; ; compilation unit finished ; Undefined variable: ; #:LIMIT ; caught 1 WARNING condition 1 2 3 4 5 --> NIL
マクロ定義が大きくなると可読性が悪くなるが、数行程度のマクロであればそれほど問題ない。