Next: , Previous: Argument Evaluation, Up: Problems with Macros


12.6.2 マクロ展開形内のローカル変数

forの新しい定義には、新たな問題があります。 ユーザーが予期していないローカル変数maxを導入しているのです。 これは、つぎのような場合、問題を引き起こします。

     (let ((max 0))
       (for x from 0 to 10 do
         (let ((this (frob x)))
           (if (< max this)
               (setq max this)))))

forの本体内でのmaxの参照は、 ユーザーが束縛したmaxを参照するものと期待されていますが、 実際にはforが作った束縛を使います。

これを修正するには、maxのかわりに、 インターンしてないシンボル(see Creating Symbols)を使います。 インターンしてないシンボルは、他のシンボルと同様に、 束縛したり参照したりできますが、forで作ったので、 ユーザープログラムには現れていないことがわかっています。 インターンしてないので、ユーザーがプログラムのあとの部分で 参照する方法もありません。 forで使った箇所以外には現れえないのです。 このように動作するforの定義をつぎに示します。

     (defmacro for (var from init to final do &rest body)
       "Execute a simple for loop: (for i from 1 to 10 do (print i))."
       (let ((tempvar (make-symbol "max")))
         `(let ((,var ,init)
                (,tempvar ,final))
            (while (<= ,var ,tempvar)
              ,@body
              (inc ,var)))))

これは、maxという名前のインターンしてないシンボルを作成し、 もとの式に現れていたインターンしたシンボルmaxのかわりに 展開形内部で使います。