dolist
MacroSuppose, for example, you want to reverse a list, so that “first” “second” “third” becomes “third” “second” “first”.
In practice, you would use the reverse
function, like this:
(setq animals '(gazelle giraffe lion tiger)) (reverse animals)
Here is how you could reverse the list using a while
loop:
(setq animals '(gazelle giraffe lion tiger)) (defun reverse-list-with-while (list) "Using while, reverse the order of LIST." (let (value) ; make sure list starts empty (while list (setq value (cons (car list) value)) (setq list (cdr list))) value)) (reverse-list-with-while animals)
And here is how you could use the dolist
macro:
(setq animals '(gazelle giraffe lion tiger)) (defun reverse-list-with-dolist (list) "Using dolist, reverse the order of LIST." (let (value) ; make sure list starts empty (dolist (element list value) (setq value (cons element value))))) (reverse-list-with-dolist animals)
In Info, you can place your cursor after the closing parenthesis of each expression and type C-x C-e; in each case, you should see
(tiger lion giraffe gazelle)
in the echo area.
For this example, the existing reverse
function is obviously best.
The while
loop is just like our first example (see A while
Loop and a List). The while
first
checks whether the list has elements; if so, it constructs a new list
by adding the first element of the list to the existing list (which in
the first iteration of the loop is nil
). Since the second
element is prepended in front of the first element, and the third
element is prepended in front of the second element, the list is reversed.
In the expression using a while
loop,
the (setq list (cdr list))
expression shortens the list, so the while
loop eventually
stops. In addition, it provides the cons
expression with a new
first element by creating a new and shorter list at each repetition of
the loop.
The dolist
expression does very much the same as the
while
expression, except that the dolist
macro does some
of the work you have to do when writing a while
expression.
Like a while
loop, a dolist
loops. What is different is
that it automatically shortens the list each time it loops—it
CDRs down the list on its own—and it automatically binds
the CAR of each shorter version of the list to the first of its
arguments.
In the example, the CAR of each shorter version of the list is
referred to using the symbol ‘element’, the list itself is called
‘list’, and the value returned is called ‘value’. The
remainder of the dolist
expression is the body.
The dolist
expression binds the CAR of each shorter
version of the list to element
and then evaluates the body of
the expression; and repeats the loop. The result is returned in
value
.