Next: Eval During Expansion, Previous: Argument Evaluation, Up: Problems with Macros
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
のかわりに
展開形内部で使います。