2.3 End-test control

2.3.1 Reference pages

while End-Test Control Clause Keyword

until End-Test Control Clause Keyword

Syntax:while expr

Syntax:until expr

Thewhile construct allows iteration to continue until the specified expression evaluates tonil. The expression is reevaluated at the location of thewhile clause.

Theuntil construct is equivalent towhile(not expr).... If the value of the specified expression is non-nil, iteration terminates.

You can usewhile anduntil at any point in a loop. If awhile oruntil clause causes termination, any clauses that precede it in the source are still evaluated.

;; 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 while stack for item = (length stack) then (pop stack) collect item)) (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)

See Also: always, never, thereis

always End-Test Control Clause Keyword

never End-Test Control Clause Keyword

thereis End-Test Control Clause Keyword

Syntax:always expr

Syntax:never expr

Syntax:thereis expr

Thealways construct takes one form and terminates the loop if the form ever evaluates tonil; in this case, it returnsnil. Otherwise, it provides a default return value oft.

Thenever construct takes one form and terminates the loop if the form ever evaluates to non-nil; in this case, it returnsnil. Otherwise, it provides a default return value oft.

Thethereis construct takes one form and terminates the loop if the form ever evaluates to non-nil; in this case, it returns that value.

If thewhile anduntil constructs cause termination, control is passed to the loop epilogue, where anyfinally clauses will be executed. Sincealways,never, andthereis use the Common Lisp macroreturn to terminate iteration, anyfinally clause that is specified is not evaluated.

;; 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 (print i)) 11 NIL

;; If you could use this code 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. Of course, this code does not 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))))))

See Also: while, until

loop-finish End-Test Control Clause Keyword

Syntax:loop-finish

The macroloop-finish terminates iteration normally and returns any accumulated result. If specified, afinally clause is evaluated.

In most cases it is not necessary to useloop-finish because other loop control clauses terminate the loop. Useloop-finish to provide a normal exit from a nested condition inside a loop.

You can useloop-finish inside nested Lisp code to provide a normal exit from a loop. Sinceloop-finish transfers control to the loop epilogue, usingloop-finish within afinally expression can cause infinite looping.

;; Print a date in February, but exclude leap year day.
;; LOOP-FINISH exits from the nested condition.
> (loop for date in date-list
        do (case date
             (29 (when (eq month february)
                       (loop-finish))
               (format t ":@(~A) ~A" month date))))

;; Terminate the loop, but return the accumulated count. > (loop for i in '(1 2 3 stop-here 4 5 6) when (symbolp i) do (loop-finish) count i) 3

;; This loop works just as well as the previous example. > (loop for i in '(1 2 3 stop-here 4 5 6) until (symbolp i) count i) 3


The Loop Facility - 9 SEP 1996

Generated with Harlequin WebMaker