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のかわりに
展開形内部で使います。