Alors que dotimes est une macro pour l'itération sur les entiers, dolist est une macro pour l'itération sur les éléments d'une liste. Sa syntaxe est similaire à celle de dotimes :
(dotimes (var lstexp finexpr)
expression-1
expression-2
...
expression-n)
Comme pour dotimes var est un symbole et les autres composants sont des expressions arbitraires. La partie finexpr est facultative, et vaudra nil par défaut.
D'abord, l'expression lstexp est évaluée une seule fois ; sa valeur doit être une liste. Puis, les expressions sont évaluées avec la valeur de la variable égale aux éléments de cette liste.
Après la dernière itération, l'expression finexpr est évaluée et sa valeur sera la valeur de l'expression dotimes entière. Pendant l'évaluation de finexpr, la valeur de la variable d'itération var est égale à nil. Exemples :
* (dolist (e '(a b c))
(print e))
A
B
C
NIL
* (dolist (e '(a b c) (list e))
(print e))
A
B
C
(NIL)
* (defparameter *l* (list 'a 'b 'c))
*L*
* (dolist (e *l*)
(pop *l*)
(print e))
A
B
C
NIL
* (defparameter *l* (list 'a 'b 'c))
*L*
* (dolist (e *l*)
(nbutlast *l*)
(print e))
A
B
NIL
*
Une affectation de la variable *l* dans la boucle (ici (pop *l*)) n'influence pas le nombre d'itérations, car *l* est évaluée une seule fois au début de la boucle. Par contre, une opération destructive sur la liste même, ici (nbutlast *l*) qui supprime le dernier élément de la liste) peut l'influencer.