eval(see Eval)を呼び出すなどして、
マクロ定義そのものの中でマクロ引数の式を評価すると、
別の問題を生じます。
引数でユーザーの変数を参照する場合、
ユーザーがマクロ引数の1つと同じ名前を使っていると、
問題になります。
マクロ本体の内側では、マクロ引数の束縛が最ローカルな束縛ですから、
そのフォームの内側からの参照は、この束縛を使います。
例を示しましょう。
(defmacro foo (a)
(list 'setq (eval a) t))
=> foo
(setq x 'b)
(foo x) ==> (setq b t)
=> t ; bを設定する
;; しかし
(setq a 'c)
(foo a) ==> (setq a t)
=> t ; cではなくaを設定する
ユーザーの引数の名前がaかxかで違いがでます。
というのは、マクロ引数の変数aとaが衝突するからです。
マクロ定義内でevalを呼び出したときの別の問題点は、
コンパイルしたプログラムでは、意図した動作をしないだろうということです。
バイトコンパイラは、プログラムをコンパイル中にマクロ定義を実行しますから、
(evalで参照したい)プログラムそのものの計算は行われず、
そのローカル変数の束縛も存在しません。
これらの問題を回避するには、 マクロ展開の計算過程では、引数の式を評価しないことです。 そのかわりに、マクロ展開では式の置換を使って、 展開時にその値が計算されるようにします。 このようにすれば、本章の他の例題は動作します。