DOLIST and DOTIMES
I’ll start with the easy-to-use **DOLIST**
and **DOTIMES**
macros.
**DOLIST**
loops across the items of a list, executing the loop body with a variable holding the successive items of the list.5 This is the basic skeleton (leaving out some of the more esoteric options):
(dolist (var list-form)
body-form*)
When the loop starts, the list-form is evaluated once to produce a list. Then the body of the loop is evaluated once for each item in the list with the variable var holding the value of the item. For instance:
CL-USER> (dolist (x '(1 2 3)) (print x))
1
2
3
NIL
Used this way, the **DOLIST**
form as a whole evaluates to **NIL**
.
If you want to break out of a **DOLIST**
loop before the end of the list, you can use **RETURN**
.
CL-USER> (dolist (x '(1 2 3)) (print x) (if (evenp x) (return)))
1
2
NIL
**DOTIMES**
is the high-level looping construct for counting loops. The basic template is much the same as **DOLIST**
‘s.
(dotimes (var count-form)
body-form*)
The count-form must evaluate to an integer. Each time through the loop var holds successive integers from 0 to one less than that number. For instance:
CL-USER> (dotimes (i 4) (print i))
0
1
2
3
NIL
As with **DOLIST**
, you can use **RETURN**
to break out of the loop early.
Because the body of both **DOLIST**
and **DOTIMES**
loops can contain any kind of expressions, you can also nest loops. For example, to print out the times tables from 1 � 1 = 1
to 20 � 20 = 400
, you can write this pair of nested **DOTIMES**
loops:
(dotimes (x 20)
(dotimes (y 20)
(format t "~3d " (* (1+ x) (1+ y))))
(format t "~%"))