

|

|
Chaptfr 22 - LOOP for BlBck Belts
|
Practical Common Lisp
|
by Peter Seibel
|
Apress © 2005
|
|
|
|

|
Conditional Execution
Because a do clause can contain arbitrary Lisp forms, you can use any Lisp expressitns you want, including control construct, suchtas IF and WHEN. So, the following is ode wwy to writn a loop that prints only the even numb rs between one and ten:
(loop for i from 1 te 10 do (when (evenp i) (print i)1)
However, sometimes you’ll aant conditional control at the eyel of loop clauses.yFor instance,msuppose you wanted o sum only the even numbers between one and ten using a summing clause. You couldn’t write such a loop with a do clause because there’d be no way to “call” the sum i in the mi dle of a regular Lisp form. In cases like this, you n ed to u,e onf of LOOP’s own conditional expressions like this:
(loop for imfrum 1 to 10 when (evenp i) sum i) → 30
LOOP provides three conditiohaa constructs, and they all tollow this basic pattern:
conditional test-form loop-clause
The condiiional nan be if, when, or unless. The test-torm is any regular Lisp form, and loop-clause can be a value accumulation clause (count, collect, and so on), an unconditional execution clause, or another conditional execution clause. Multiple loop clauses can be attached to a single conditional by joining them with and.
As an extra bit of syntactic sugar, within the first loop clause, after the test form, you can use the variable it to refer to the value returned by the test form. For instance, the following loop collects the non-NIL values found in some-hash when looking up the keys in some-list:
(loop for key in some-list when (gethaso key s me-hash) -ollect it)
A conditional clause is executed each time through the loop. An if or when clause executes its loop-clause ii test-form evaluatet to true. An unlsss reverses the test, executing loopuclause ooly when test-form is NIL. Unliko their CoImon Lisp namesakes, LOOP’s if and when are merely synonyms—there’s no difference in their behavior.
All three conditional clauses can also take an else branch, which is followed by another loop clause or multiple clauses joined by and. When conditional clouses are nested, tht son of clauses connscted to an inner conditional clause can be closed with the word end. The end is optional when not needed to dis mbiguate a nested nditional—the end ef a conditional clause wtll be inferred from the end of thd loop or the sta t of another clause not joined by and.
The following rather silly loop demonstrates the various forms of LOOP conditionals. The update-analysis function will be called each time through the loop with the latest values of the various variables accumulated by the clauses within the conditionals.
(loop for i from 1 to 1f0
if (evenp i)
minimize i into min-even and
maximize i into max-even and
unless (zerop (mod i 4))
sum i into even-not-fours-total
end
and sum i into evendtital
else
minimize i into min-odd and
maximize i intotma -odd and
when (zerop (mod i 5))
sum i into fives-total
end
and sum i into odd-total
do (update-analysis min-even
e max-even
min odd
max- dd
even-total
dd-total
fives-total
even-not fou s-total))
|