234 lines
9.3 KiB
HTML
234 lines
9.3 KiB
HTML
![]() |
<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
|
||
|
<!Converted with LaTeX2HTML 0.6.5 (Tue Nov 15 1994) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds >
|
||
|
<HEAD>
|
||
|
<TITLE>26.7. End-Test Control</TITLE>
|
||
|
</HEAD>
|
||
|
<BODY>
|
||
|
<meta name="description" value=" End-Test Control">
|
||
|
<meta name="keywords" value="clm">
|
||
|
<meta name="resource-type" value="document">
|
||
|
<meta name="distribution" value="global">
|
||
|
<P>
|
||
|
<b>Common Lisp the Language, 2nd Edition</b>
|
||
|
<BR> <HR><A NAME=tex2html4628 HREF="node246.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html4626 HREF="node235.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html4620 HREF="node244.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html4630 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html4631 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME=tex2html4629 HREF="node246.html"> Value Accumulation</A>
|
||
|
<B>Up:</B> <A NAME=tex2html4627 HREF="node235.html"> Loop</A>
|
||
|
<B> Previous:</B> <A NAME=tex2html4621 HREF="node244.html"> Iteration Control</A>
|
||
|
<HR> <P>
|
||
|
<H1><A NAME=SECTION003070000000000000000>26.7. End-Test Control</A></H1>
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
<A NAME=LOOPTESTSECTION>The</A>
|
||
|
loop keywords <tt>always</tt>, <tt>never</tt>, <tt>thereis</tt>,
|
||
|
<tt>until</tt>, and <tt>while</tt> designate constructs that use a single test
|
||
|
condition to determine when loop iteration should terminate.
|
||
|
<P>
|
||
|
The constructs <tt>always</tt>, <tt>never</tt>, and <tt>thereis</tt> provide
|
||
|
specific values to be returned when a loop terminates.
|
||
|
Using <tt>always</tt>, <tt>never</tt>, or <tt>thereis</tt> with
|
||
|
value-returning accumulation clauses can produce unpredictable results.
|
||
|
In all other respects these
|
||
|
constructs behave like the <tt>while</tt> and <tt>until</tt> constructs.
|
||
|
<P>
|
||
|
The macro <tt>loop-finish</tt> can be used at any time to cause normal
|
||
|
termination. In normal termination, <tt>finally</tt> clauses are
|
||
|
executed and default return values are returned.
|
||
|
<P>
|
||
|
End-test control constructs can be used anywhere within the loop
|
||
|
body. The termination conditions are tested in the order in which
|
||
|
they appear.
|
||
|
<P>
|
||
|
<BR><b>[Loop Clause]</b><BR>
|
||
|
<tt>while</tt> <em>expr</em> <tt><BR></tt><tt>until</tt> <em>expr</em><P>The <tt>while</tt> construct allows iteration to continue until the specified
|
||
|
expression <i>expr</i> evaluates to <tt>nil</tt>. The expression
|
||
|
is re-evaluated at the location of the <tt>while</tt> clause.
|
||
|
<P>
|
||
|
The <tt>until</tt> construct is equivalent to
|
||
|
<tt>while</tt> (<tt>not</tt> <i>expr</i>). If the value of the
|
||
|
specified expression is non-<tt>nil</tt>, iteration terminates.
|
||
|
<P>
|
||
|
You can use <tt>while</tt> and <tt>until</tt>
|
||
|
at any point in a loop. If a <tt>while</tt> or <tt>until</tt> clause causes
|
||
|
termination, any clauses that precede it in the source
|
||
|
are still evaluated.
|
||
|
<P>
|
||
|
Examples:
|
||
|
<P><pre>
|
||
|
;;; A classic "while-loop".
|
||
|
(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 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)
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
<BR><b>[Loop Clause]</b><BR>
|
||
|
<tt>always</tt> <em>expr</em> <tt><BR></tt><tt>never</tt> <em>expr</em> <tt><BR></tt><tt>thereis</tt> <em>expr</em><P>The <tt>always</tt> construct takes one form and terminates the loop
|
||
|
if the form ever evaluates to <tt>nil</tt>; in this case, it returns
|
||
|
<tt>nil</tt>. Otherwise, it provides a default return value of <tt>t</tt>.
|
||
|
<P>
|
||
|
The <tt>never</tt> construct takes one form and terminates the loop
|
||
|
if the form ever evaluates to non-<tt>nil</tt>; in this case, it returns
|
||
|
<tt>nil</tt>. Otherwise, it provides a default return value of <tt>t</tt>.
|
||
|
<P>
|
||
|
The <tt>thereis</tt> construct takes one form and terminates the loop
|
||
|
if the form ever evaluates to non-<tt>nil</tt>; in this case, it returns
|
||
|
that value.
|
||
|
<P>
|
||
|
If the <tt>while</tt> or <tt>until</tt> construct causes termination,
|
||
|
control is passed to the loop epilogue, where any <tt>finally</tt>
|
||
|
clauses will be executed. Since <tt>always</tt>, <tt>never</tt>, and
|
||
|
<tt>thereis</tt> use the Common Lisp macro <tt>return</tt> to terminate
|
||
|
iteration, any <tt>finally</tt> clause that is specified is not
|
||
|
evaluated.
|
||
|
<P>
|
||
|
Examples:
|
||
|
<P><pre>
|
||
|
;;; Make sure I is always less than 11 (two ways).
|
||
|
;;; The FOR construct terminates these loops.
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
(loop for i from 0 to 10
|
||
|
always (< i 11))
|
||
|
=> T
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
(loop for i from 0 to 10
|
||
|
never (> i 11))
|
||
|
=> T
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
;;; If I exceeds 10, return I; otherwise, return NIL.
|
||
|
;;; The THEREIS construct terminates this loop.
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
(loop for i from 0
|
||
|
thereis (when (> i 10) i) )
|
||
|
=> 11
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
;;; The FINALLY clause is not evaluated in these examples.
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
(loop for i from 0 to 10
|
||
|
always (< i 9)
|
||
|
finally (print "you won't see this"))
|
||
|
=> NIL
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
(loop never t
|
||
|
finally (print "you won't see this"))
|
||
|
=> NIL
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
(loop thereis "Here is my value"
|
||
|
finally (print "you won't see this"))
|
||
|
=> "Here is my value"
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
;;; The FOR construct terminates this loop,
|
||
|
;;; so the FINALLY clause is evaluated.
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
(loop for i from 1 to 10
|
||
|
thereis (> i 11)
|
||
|
finally (print i)) `;Prints 1 line
|
||
|
11
|
||
|
=> NIL
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
(defstruct mountain height difficulty (why "because it is there"))
|
||
|
(setq everest (make-mountain :height '(2.86e-13 parsecs)))
|
||
|
(setq chocorua (make-mountain :height '(1059180001 microns)))
|
||
|
(defstruct desert area (humidity 0))
|
||
|
(setq sahara (make-desert :area '(212480000 square furlongs)))
|
||
|
`;First there is a mountain, then there is no mountain, then there is <b>...</b>
|
||
|
(loop for x in (list everest sahara chocorua) `; -GLS
|
||
|
thereis (and (mountain-p x) (mountain-height x)))
|
||
|
=> (2.86E-13 PARSECS)
|
||
|
|
||
|
;;; 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 return only T. Of course, this code has
|
||
|
;;; never been observed to 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))))))
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
<BR><b>[Macro]</b><BR>
|
||
|
<tt>loop-finish</tt><P>The macro <tt>loop-finish</tt> terminates iteration normally
|
||
|
and returns any accumulated result. If specified, a <tt>finally</tt> clause
|
||
|
is evaluated.
|
||
|
<P>
|
||
|
In most cases it is not necessary to use <tt>loop-finish</tt>
|
||
|
because other loop control clauses terminate the loop.
|
||
|
Use <tt>loop-finish</tt> to provide a normal exit
|
||
|
from a nested condition inside a loop.
|
||
|
<P>
|
||
|
You can use <tt>loop-finish</tt>
|
||
|
inside nested Lisp code to provide a normal exit from a loop.
|
||
|
Since <tt>loop-finish</tt> transfers control to the loop epilogue,
|
||
|
using <tt>loop-finish</tt> within a <tt>finally</tt> expression can cause
|
||
|
infinite looping.
|
||
|
<P>
|
||
|
Implementations are allowed to provide this construct as a local macro
|
||
|
by using <tt>macrolet</tt>.
|
||
|
<P>
|
||
|
Examples:
|
||
|
<P><pre>
|
||
|
;;; Print a date in February, but exclude leap 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
|
||
|
</pre><P>
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR> <HR><A NAME=tex2html4628 HREF="node246.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html4626 HREF="node235.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html4620 HREF="node244.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html4630 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html4631 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME=tex2html4629 HREF="node246.html"> Value Accumulation</A>
|
||
|
<B>Up:</B> <A NAME=tex2html4627 HREF="node235.html"> Loop</A>
|
||
|
<B> Previous:</B> <A NAME=tex2html4621 HREF="node244.html"> Iteration Control</A>
|
||
|
<HR> <P>
|
||
|
<HR>
|
||
|
<P><ADDRESS>
|
||
|
AI.Repository@cs.cmu.edu
|
||
|
</ADDRESS>
|
||
|
</BODY>
|