So, I can loop with one variable like this:
(loop for i in '(1 2 3 4 5) do (print i))
I can get 1 number and bind it to i.
But how can I bind to more than 1 variable at once, e.g. something like:
for i,j,k in '(1 2 3 4 5)
-> i = 1, j = 2, k = 3
I already tried searching around but only found with
statement to define more variables, but it does not allow me to bind the variables directly.
To elaborate on the other answer. If you simply wish to iterate with multiple variables then then you can do this by
(loop for x ...
for y ...
do ...)
This does sequential binding: when y
is stepped, x
has already been stepped. Parallel binding happens with and
:
(loop for x ...
and y ...
do ...)
If you want to destructure a single list, then you can use destructuring. But the destructuring loop
does is kind of horrible, and in particular it is not, of course, compatible with the destructuring done b destructuring-bind
or (equivalently) macro lambda lists. In particular as the other answer shows (a b c)
does match (1 2 3 4 5 6)
, or indeed ()
.
However the other answer is probably unsafe in general. Consider this function:
(defun foo (l)
(loop for (a b c) on l by #'cddr
while c
do (print (list a b c))))
Well now consider (foo '(1 2 nil 3 4 5))
.
A better approach is this, which both avoids the worst horrors of loop
's destructuring, and gets the termination condition closer to right, as well as being, probably, slightly more efficient:
(defun foo (l)
(loop for (a b c . tail) = l then tail
do (print (list a b c))
while tail))
Now
> (foo '(1 2 nil 3 4 5))
(1 2 nil)
(3 4 5)
nil