健全なマクロ
マクロ処理の過程の過程で見かけ上同じに見える識別子が発生(名前が衝突)しても、意図しない問題が起こらないことが保証されているマクロのことである。
健全なマクロの機能を持たないプログラミング言語では、マクロの展開中に作成された変数の束縛によって、すでに存在する変数の束縛が隠されてしまう可能性がある。
不健全なマクロ
code:c
int main (void) {
int a=0, b=0;
incr(a);
incr(b);
printf("a=%d, b=%d\n", a, b);
return 0;
}
/* 展開後 */
int main (void) {
int a=0, b=0;
{int a=0; ++a;}
{int a=0; ++b;} /* ここで a が再宣言されている */
printf("a=%d, b=%d\n", a, b); /* a=0, b=1 */
return 0;
}
Common Lisp でも発生する可能性があり、その場合は gensym を使って回避した記憶 radish_miyazaki.icon ちょうど探していた内容の記事があった radish_miyazaki.icon
以前に Clojure のマクロについてまとめた
構文クォートの中で、名前空間の修飾のない名前にハッシュ記号(#)を付けると、Clojure はアンダースコアとユニークなIDを付けた名前を持つ、自動生成されたシンボル(auto-gensym)を作り出す。
code:clojure
(if (not x#)
~then
~else)))
(unless false
(printf "x: %s%n" x) ;; x: 10
(println "TRUE")))
(use 'clojure.walk)
;; 展開処理
(macroexpand-all '(let x 10 (unless false
(printf "x: %s%n" x)
(println "TRUE"))))
;; 展開結果
(if (clojure.core/not x__2__auto__)
(printf "x: %s%n" x)
(println "TRUE"))))