DO and it ilk _bind_ their initial values, so that you get local
index-variables inside the loop, but they _assign_ their updated values.
See CLtL II, pages 165-166; for DO, "the assignment of values to
variables is done in parallel, as if by PSETQ". For DO*, "the
assignment of values to variables is done setquentially, as if by SETQ".
Therefore, you won't get a new closure-variable on each iteration.
(mapcar #'funcall (do ((n 0 (1+ n))
(z '() (cons #'(lambda () n) z)))
((= n 3) z)))
returns (3 3 3). It's trivial to get separate variables:
(mapcar #'funcall (do ((n 0 (1+ n))
(z '() (cons (let ((n n)) #'(lambda () n)) z)))
((= n 3) z)))
returns (2 1 0).