Unlike the loops in nearly every other programming language in use today, the LOOP
in Common Lisp can be used as an expression:
(let ((doubled (loop for x from 1 to 10
collect (* 2 x))))
doubled) ;; ==> (2 4 6 8 10 12 14 16 18 20)
(loop for x from 1 to 10 sum x)
MAXIMIZE
causes the LOOP
to return the largest value
that was evaluated. MINIMIZE
is the opposite of
MAXIMIZE
.
(loop repeat 100
for x = (random 1000)
maximize x)
COUNT
tells you how many times an expression evaluated to non-NIL
during the loop:
(loop repeat 100
for x = (random 1000)
count (evenp x))
LOOP
also has equivalents of the some
, every
, and notany
functions:
(loop for ch across "foobar"
thereis (eq ch #\a))
(loop for x in '(a b c d e f 1)
always (symbolp x))
(loop for x in '(1 3 5 7)
never (evenp x))
...except they're not limited to iterating over sequences:
(loop for value = (read *standard-input* nil :eof)
until (eq value :eof)
never (stringp value))
LOOP
value-generating verbs can also be written
with an -ing suffix:
(loop repeat 100
for x = (random 1000)
minimizing x)
It is also possible to capture the value generated by these verbs into variables (which are created implicitly by the LOOP
macro),
so you can generate more than one value at a time:
(loop repeat 100
for x = (random 1000)
maximizing x into biggest
minimizing x into smallest
summing x into total
collecting x into xs
finally (return (values biggest smallest total xs)))
You can have more than one collect
, count
, etc. clause that collects
into the same output value. They will be executed in sequence.
The following converts an association list (which you can use with assoc
) into a property list (which you can use with getf
):
(loop for (key . value) in assoc-list
collect key
collect value)
Although this is better style:
(loop for (key . value) in assoc-list
append (list key value))