The repeat
construct causes iteration to terminate after a
specified number of times.
The loop body executes n times, where n is the value
of the expression form. The form argument is evaluated one time
in the loop prologue. If the expression evaluates to 0 or
to a negative number, the loop body is not evaluated.
The constructs always
,
never
,
thereis
,
while
,
until
,
and the macro loop-finish
allow conditional termination of iteration within
a loop
.
The constructs always
, never
, and thereis
provide
specific values to be returned when a loop
terminates.
Using always
, never
, or thereis
in a loop with
value accumulation clauses that are not into
causes
an error of type program-error
to be signaled (at macro expansion time).
Since always
, never
, and thereis
use
the return-from
special operator
to terminate iteration,
any finally
clause that is supplied is not evaluated
when exit occurs due to any of these constructs.
In all other respects these
constructs behave like the while
and until
constructs.
The always
construct takes one form and terminates the
loop
if the form ever evaluates to nil
; in this case, it returns
nil
. Otherwise, it provides a default return value of t
.
If the value of the supplied form is never nil
, some other construct
can terminate the iteration.
The never
construct terminates iteration the first time that
the value of the supplied form is non-nil; the loop
returns
nil
.
If the value of the supplied form is always nil
, some other
construct can terminate the iteration.
Unless some other clause contributes
a return value, the default value returned is t
.
The thereis
construct terminates iteration the first time that the
value of the supplied form is non-nil; the loop
returns the
value of the supplied form.
If the value of the supplied form
is always nil
, some other
construct can terminate the iteration. Unless some other clause contributes a
return value, the default value returned is nil
.
There are two differences between the thereis
and until
constructs:
until
construct does not return a value or
nil
based on the value of the supplied form.
until
construct executes
any finally
clause.
Since thereis
uses
the return-from
special operator
to terminate iteration,
any finally
clause that is supplied is not evaluated
when exit occurs due to thereis
.
The while
construct allows iteration to continue until the
supplied form
evaluates to false. The supplied form
is reevaluated at the location of the while
clause.
The until
construct is equivalent to
while (not
form)...
. If the value of the
supplied form is non-nil, iteration terminates.
Termination-test control constructs can be used anywhere within the loop body.
The termination tests are used in the order in which they appear.
If an until
or while
clause causes
termination, any clauses that precede it in the source
are still evaluated.
If the until
and while
constructs cause termination,
control is passed to the loop epilogue, where any finally
clauses will be executed.
There are two differences between the never
and until
constructs:
until
construct does not return
t
or nil
based on the value of the supplied form.
until
construct
does not bypass any finally
clauses.
Since never
uses
the return-from
special operator
to terminate iteration,
any finally
clause that is supplied is not evaluated
when exit occurs due to never
.
In most cases it is not necessary to use loop-finish
because other loop control clauses terminate the loop
.
The macro loop-finish
is used to provide a normal exit
from a nested conditional inside a loop
.
Since loop-finish
transfers control to the loop epilogue,
using loop-finish
within a finally
expression can cause
infinite looping.
(loop repeat 3 do (format t "~&What I say three times is true.~%")) ▷ What I say three times is true. ▷ What I say three times is true. ▷ What I say three times is true. → NIL (loop repeat -15 do (format t "What you see is what you expect~%")) → NIL
;; Make sure I is always less than 11 (two ways). ;; The FOR construct terminates these loops. (loop for i from 0 to 10 always (< i 11)) → T (loop for i from 0 to 10 never (> i 11)) → T ;; If I exceeds 10 return I; otherwise, return NIL. ;; The THEREIS construct terminates this loop. (loop for i from 0 thereis (when (> i 10) i) ) → 11 ;;; The FINALLY clause is not evaluated in these examples. (loop for i from 0 to 10 always (< i 9) finally (print "you won't see this")) → NIL (loop never t finally (print "you won't see this")) → NIL (loop thereis "Here is my value" finally (print "you won't see this")) → "Here is my value" ;; The FOR construct terminates this loop, so the FINALLY clause ;; is evaluated. (loop for i from 1 to 10 thereis (> i 11) finally (prin1 'got-here)) ▷ GOT-HERE → NIL ;; If this code could be used to find a counterexample to Fermat's ;; last theorem, it would still not return the value of the ;; counterexample because all of the THEREIS clauses in this example ;; only return T. But if Fermat is right, that won't matter ;; because this won't terminate. (loop for z upfrom 2 thereis (loop for n upfrom 3 below (log z 2) thereis (loop for x below z thereis (loop for y below z thereis (= (+ (expt x n) (expt y n)) (expt z n))))))
(loop while (hungry-p) do (eat)) ;; UNTIL NOT is equivalent to WHILE. (loop until (not (hungry-p)) do (eat)) ;; Collect the length and the items of STACK. (let ((stack '(a b c d e f))) (loop for item = (length stack) then (pop stack) collect item while stack)) → (6 A B C D E F) ;; Use WHILE to terminate a loop that otherwise wouldn't terminate. ;; Note that WHILE occurs after the WHEN. (loop for i fixnum from 3 when (oddp i) collect i while (< i 5)) → (3 5)