CL の経験はあまりありませんが、Scheme で多くの作業を行いました。
2 番目のバージョン (sans setf a) では、remove-if 式が評価されますが、実際に a を変更することは何もしません。loop は CL のマクロであり、式を評価するだけですが、再帰関数のようにそれらの式の結果を使用しません。
そのため、最初のバージョンでは、setf によってループが実行されるたびに a の値が変更されますが、2 番目のバージョンでは、a の値は一貫して一定です。したがって、(car a) は変化せず、ループは終了しません。
両方のループ ステートメントで macroexpand の結果を比較できます。
setf なし:
(MACROLET ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-ERROR)))
(BLOCK NIL
(LET NIL
(MACROLET ((LOOP-FINISH NIL '(GO SYSTEM::END-LOOP)))
(TAGBODY SYSTEM::BEGIN-LOOP
(PROGN (UNLESS (< (CAR A) X) (LOOP-FINISH))
(PROGN (PUSH (CAR A) B) (REMOVE-IF #'(LAMBDA (M) (= 0 (MOD M (CAR A)))) A)))
(GO SYSTEM::BEGIN-LOOP) SYSTEM::END-LOOP
(MACROLET
((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-WARN) '(GO SYSTEM::END-LOOP))))))))) ;
setf を使用:
(MACROLET ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-ERROR)))
(BLOCK NIL
(LET NIL
(MACROLET ((LOOP-FINISH NIL '(GO SYSTEM::END-LOOP)))
(TAGBODY SYSTEM::BEGIN-LOOP
(PROGN (UNLESS (< (CAR A) X) (LOOP-FINISH))
(PROGN (PUSH (CAR A) B)
(SETF A (REMOVE-IF #'(LAMBDA (M) (= 0 (MOD M (CAR A))))) A)))
(GO SYSTEM::BEGIN-LOOP) SYSTEM::END-LOOP
(MACROLET
((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-WARN) '(GO SYSTEM::END-LOOP))))))))) ;
最初のループで remove-if 式が評価されていることがわかりますが、その結果は使用されていません。