1
0
Fork 0
cl-sites/HyperSpec-7-0/HyperSpec/Body/m_do_do.htm
2024-04-01 10:24:07 +02:00

156 lines
16 KiB
HTML

<!-- Common Lisp HyperSpec (TM), version 7.0 generated by Kent M. Pitman on Mon, 11-Apr-2005 2:31am EDT -->
<HTML>
<HEAD>
<TITLE>CLHS: Macro DO, DO*</TITLE>
<LINK HREF="../Data/clhs.css" REL="stylesheet" TYPE="text/css" />
<META HTTP-EQUIV="Author" CONTENT="Kent M. Pitman">
<META HTTP-EQUIV="Organization" CONTENT="LispWorks Ltd.">
<LINK REL=TOP HREF="../Front/index.htm">
<LINK REL=COPYRIGHT HREF="../Front/Help.htm#Legal">
<LINK REL=DISCLAIMER HREF="../Front/Help.htm#Disclaimer">
<LINK REL=PREV HREF="c_iterat.htm">
<LINK REL=UP HREF="c_iterat.htm">
<LINK REL=NEXT HREF="m_dotime.htm">
</HEAD>
<BODY>
<H1><A REV=MADE HREF="http://www.lispworks.com/"><IMG WIDTH=80 HEIGHT=65 ALT="[LISPWORKS]" SRC="../Graphics/LWSmall.gif" ALIGN=Bottom></A><A REL=TOP HREF="../Front/index.htm"><IMG WIDTH=237 HEIGHT=65 ALT="[Common Lisp HyperSpec (TM)]" SRC="../Graphics/CLHS_Sm.gif" ALIGN=Bottom></A> <A REL=PREV HREF="c_iterat.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="c_iterat.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="m_dotime.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
<HR>
<A NAME="do"><A NAME="doST"><I>Macro</I> <B>DO, DO*</B></A></A> <P>
<P>
<P><B>Syntax:</B><P>
<P>
<B>do</B> <I>({<I>var</I> | (<I>var</I> [init-form [step-form]])}*) (end-test-form <I>result-form</I><B>*</B>) <I>declaration</I><B>*</B> {tag | statement}*</I><P> =&gt; <I><I>result</I><B>*</B></I><P>
<P>
<B>do*</B> <I>({<I>var</I> | (<I>var</I> [init-form [step-form]])}*) (end-test-form <I>result-form</I><B>*</B>) <I>declaration</I><B>*</B> {tag | statement}*</I><P> =&gt; <I><I>result</I><B>*</B></I><P>
<P>
<P><B>Arguments and Values:</B><P>
<P>
<I>var</I>---a <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbol</I></A>. <P>
<I>init-form</I>---a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A>. <P>
<I>step-form</I>---a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A>. <P>
<I>end-test-form</I>---a <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A>. <P>
<I>result-forms</I>---an <A REL=DEFINITION HREF="26_glo_i.htm#implicit_progn"><I>implicit progn</I></A>. <P>
<I>declaration</I>---a <A REL=DEFINITION HREF="s_declar.htm#declare"><B>declare</B></A> <A REL=DEFINITION HREF="26_glo_e.htm#expression"><I>expression</I></A>; not evaluated. <P>
<I>tag</I>---a <A REL=DEFINITION HREF="26_glo_g.htm#go_tag"><I>go tag</I></A>; not evaluated. <P>
<I>statement</I>---a <A REL=DEFINITION HREF="26_glo_c.htm#compound_form"><I>compound form</I></A>; evaluated as described below. <P>
<I>results</I>---if a <A REL=DEFINITION HREF="m_return.htm#return"><B>return</B></A> or <A REL=DEFINITION HREF="s_ret_fr.htm#return-from"><B>return-from</B></A> form is executed, the <A REL=DEFINITION HREF="26_glo_v.htm#value"><I>values</I></A> passed from that <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A>; otherwise, the <A REL=DEFINITION HREF="26_glo_v.htm#value"><I>values</I></A> returned by the <I>result-forms</I>. <P>
<P><B>Description:</B><P>
<P>
<A REL=DEFINITION HREF="#do"><B>do</B></A> iterates over a group of <I>statements</I> while a test condition holds. <A REL=DEFINITION HREF="#do"><B>do</B></A> accepts an arbitrary number of iteration <I>vars</I> which are bound within the iteration and stepped in parallel. An initial value may be supplied for each iteration variable by use of an <I>init-form</I>. <I>Step-forms</I> may be used to specify how the <I>vars</I> should be updated on succeeding iterations through the loop. <I>Step-forms</I> may be used both to generate successive values or to accumulate results. If the <I>end-test-form</I> condition is met prior to an execution of the body, the iteration terminates. <I>Tags</I> label <I>statements</I>. <P>
<A REL=DEFINITION HREF="#doST"><B>do*</B></A> is exactly like <A REL=DEFINITION HREF="#do"><B>do</B></A> except that the <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>bindings</I></A> and steppings of the <I>vars</I> are performed sequentially rather than in parallel. <P>
Before the first iteration, all the <I>init-forms</I> are evaluated, and each <I>var</I> is bound to the value of its respective <I>init-form</I>, if supplied. This is a <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>binding</I></A>, not an assignment; when the loop terminates, the old values of those variables will be restored. For <A REL=DEFINITION HREF="#do"><B>do</B></A>, all of the <I>init-forms</I> are evaluated before any <I>var</I> is bound. The <I>init-forms</I> can refer to the <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>bindings</I></A> of the <I>vars</I> visible before beginning execution of <A REL=DEFINITION HREF="#do"><B>do</B></A>. For <A REL=DEFINITION HREF="#doST"><B>do*</B></A>, the first <I>init-form</I> is evaluated, then the first <I>var</I> is bound to that value, then the second <I>init-form</I> is evaluated, then the second <I>var</I> is bound, and so on; in general, the <I>k</I>th <I>init-form</I> can refer to the new binding of the <I>j</I>th <I>var</I> if <I>j</I> &lt; <I>k</I>, and otherwise to the old binding of the <I>j</I>th <I>var</I>. <P>
At the beginning of each iteration, after processing the variables, the <I>end-test-form</I> is evaluated. If the result is <A REL=DEFINITION HREF="26_glo_f.htm#false"><I>false</I></A>, execution proceeds with the body of the <A REL=DEFINITION HREF="#do"><B>do</B></A> (or <A REL=DEFINITION HREF="#doST"><B>do*</B></A>) form. If the result is <A REL=DEFINITION HREF="26_glo_t.htm#true"><I>true</I></A>, the <I>result-forms</I> are evaluated in order as an <A REL=DEFINITION HREF="26_glo_i.htm#implicit_progn"><I>implicit progn</I></A>, and then <A REL=DEFINITION HREF="#do"><B>do</B></A> or <A REL=DEFINITION HREF="#doST"><B>do*</B></A> returns. <P>
At the beginning of each iteration other than the first, <I>vars</I> are updated as follows. All the <I>step-forms</I>, if supplied, are evaluated, from left to right, and the resulting values are assigned to the respective <I>vars</I>. Any <I>var</I> that has no associated <I>step-form</I> is not assigned to. For <A REL=DEFINITION HREF="#do"><B>do</B></A>, all the <I>step-forms</I> are evaluated before any <I>var</I> is updated; the assignment of values to <I>vars</I> is done in parallel, as if by <A REL=DEFINITION HREF="m_psetq.htm#psetq"><B>psetq</B></A>. Because all of the <I>step-forms</I> are evaluated before any of the <I>vars</I> are altered, a <I>step-form</I> when evaluated always has access to the old values of all the <I>vars</I>, even if other <I>step-forms</I> precede it. For <A REL=DEFINITION HREF="#doST"><B>do*</B></A>, the first <I>step-form</I> is evaluated, then the value is assigned to the first <I>var</I>, then the second <I>step-form</I> is evaluated, then the value is assigned to the second <I>var</I>, and so on; the assignment of values to variables is done sequentially, as if by <A REL=DEFINITION HREF="s_setq.htm#setq"><B>setq</B></A>. For either <A REL=DEFINITION HREF="#do"><B>do</B></A> or <A REL=DEFINITION HREF="#doST"><B>do*</B></A>, after the <I>vars</I> have been updated, the <I>end-test-form</I> is evaluated as described above, and the iteration continues. <P>
The remainder of the <A REL=DEFINITION HREF="#do"><B>do</B></A> (or <A REL=DEFINITION HREF="#doST"><B>do*</B></A>) form constitutes an <A REL=DEFINITION HREF="26_glo_i.htm#implicit_tagbody"><I>implicit tagbody</I></A>. <I>Tags</I> may appear within the body of a <A REL=DEFINITION HREF="#do"><B>do</B></A> loop for use by <A REL=DEFINITION HREF="s_go.htm#go"><B>go</B></A> statements appearing in the body (but such <A REL=DEFINITION HREF="s_go.htm#go"><B>go</B></A> statements may not appear in the variable specifiers, the <I>end-test-form</I>, or the <I>result-forms</I>). When the end of a <A REL=DEFINITION HREF="#do"><B>do</B></A> body is reached, the next iteration cycle (beginning with the evaluation of <I>step-forms</I>) occurs. <P>
An <A REL=DEFINITION HREF="26_glo_i.htm#implicit_block"><I>implicit block</I></A> named <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A> surrounds the entire <A REL=DEFINITION HREF="#do"><B>do</B></A> (or <A REL=DEFINITION HREF="#doST"><B>do*</B></A>) form. A <A REL=DEFINITION HREF="m_return.htm#return"><B>return</B></A> statement may be used at any point to exit the loop immediately. <P>
<I>Init-form</I> is an initial value for the <I>var</I> with which it is associated. If <I>init-form</I> is omitted, the initial value of <I>var</I> is <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A>. If a <I>declaration</I> is supplied for a <I>var</I>, <I>init-form</I> must be consistent with the <I>declaration</I>. <P>
<I>Declarations</I> can appear at the beginning of a <A REL=DEFINITION HREF="#do"><B>do</B></A> (or <A REL=DEFINITION HREF="#doST"><B>do*</B></A>) body. They apply to code in the <A REL=DEFINITION HREF="#do"><B>do</B></A> (or <A REL=DEFINITION HREF="#doST"><B>do*</B></A>) body, to the <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>bindings</I></A> of the <A REL=DEFINITION HREF="#do"><B>do</B></A> (or <A REL=DEFINITION HREF="#doST"><B>do*</B></A>) <I>vars</I>, to the <I>step-forms</I>, to the <I>end-test-form</I>, and to the <I>result-forms</I>. <P>
<P><B>Examples:</B><P>
<PRE>
(do ((temp-one 1 (1+ temp-one))
(temp-two 0 (1- temp-two)))
((&gt; (- temp-one temp-two) 5) temp-one)) =&gt; 4
(do ((temp-one 1 (1+ temp-one))
(temp-two 0 (1+ temp-one)))
((= 3 temp-two) temp-one)) =&gt; 3
(do* ((temp-one 1 (1+ temp-one))
(temp-two 0 (1+ temp-one)))
((= 3 temp-two) temp-one)) =&gt; 2
(do ((j 0 (+ j 1)))
(nil) ;Do forever.
(format t &quot;~%Input ~D:&quot; j)
(let ((item (read)))
(if (null item) (return) ;Process items until NIL seen.
(format t &quot;~&amp;Output ~D: ~S&quot; j item))))
&gt;&gt; Input 0: banana
&gt;&gt; Output 0: BANANA
&gt;&gt; Input 1: (57 boxes)
&gt;&gt; Output 1: (57 BOXES)
&gt;&gt; Input 2: NIL
=&gt; NIL
(setq a-vector (vector 1 nil 3 nil))
(do ((i 0 (+ i 1)) ;Sets every null element of a-vector to zero.
(n (array-dimension a-vector 0)))
((= i n))
(when (null (aref a-vector i))
(setf (aref a-vector i) 0))) =&gt; NIL
a-vector =&gt; #(1 0 3 0)
</PRE>
</TT> <P>
<PRE>
(do ((x e (cdr x))
(oldx x x))
((null x))
body)
</PRE>
</TT> is an example of parallel assignment to index variables. On the first iteration, the value of <TT>oldx</TT> is whatever value <TT>x</TT> had before the <A REL=DEFINITION HREF="#do"><B>do</B></A> was entered. On succeeding iterations, <TT>oldx</TT> contains the value that <TT>x</TT> had on the previous iteration. <P>
<PRE>
(do ((x foo (cdr x))
(y bar (cdr y))
(z '() (cons (f (car x) (car y)) z)))
((or (null x) (null y))
(nreverse z)))
</PRE>
</TT> does the same thing as <TT>(mapcar #'f foo bar)</TT>. The step computation for <TT>z</TT> is an example of the fact that variables are stepped in parallel. Also, the body of the loop is empty. <P>
<PRE>
(defun list-reverse (list)
(do ((x list (cdr x))
(y '() (cons (car x) y)))
((endp x) y)))
</PRE>
</TT> <P>
As an example of nested iterations, consider a data structure that is a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> of <A REL=DEFINITION HREF="26_glo_c.htm#cons"><I>conses</I></A>. The <A REL=DEFINITION HREF="26_glo_c.htm#car"><I>car</I></A> of each <A REL=DEFINITION HREF="26_glo_c.htm#cons"><I>cons</I></A> is a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> of <A REL=DEFINITION HREF="26_glo_s.htm#symbol"><I>symbols</I></A>, and the <A REL=DEFINITION HREF="26_glo_c.htm#cdr"><I>cdr</I></A> of each <A REL=DEFINITION HREF="26_glo_c.htm#cons"><I>cons</I></A> is a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> of equal length containing corresponding values. Such a data structure is similar to an association list, but is divided into ``frames''; the overall structure resembles a rib-cage. A lookup function on such a data structure might be: <P>
<PRE>
(defun ribcage-lookup (sym ribcage)
(do ((r ribcage (cdr r)))
((null r) nil)
(do ((s (caar r) (cdr s))
(v (cdar r) (cdr v)))
((null s))
(when (eq (car s) sym)
(return-from ribcage-lookup (car v)))))) =&gt; RIBCAGE-LOOKUP
</PRE>
</TT> <P>
<P><B>Affected By:</B> None.
<P>
<P><B>Exceptional Situations:</B> None.
<P>
<P><B>See Also:</B><P>
<P>
other iteration functions (<A REL=DEFINITION HREF="m_dolist.htm#dolist"><B>dolist</B></A>, <A REL=DEFINITION HREF="m_dotime.htm#dotimes"><B>dotimes</B></A>, and <A REL=DEFINITION HREF="m_loop.htm#loop"><B>loop</B></A>) and more primitive functionality (<A REL=DEFINITION HREF="s_tagbod.htm#tagbody"><B>tagbody</B></A>, <A REL=DEFINITION HREF="s_go.htm#go"><B>go</B></A>, <A REL=DEFINITION HREF="s_block.htm#block"><B>block</B></A>, <A REL=DEFINITION HREF="m_return.htm#return"><B>return</B></A>, <A REL=DEFINITION HREF="s_let_l.htm#let"><B>let</B></A>, and <A REL=DEFINITION HREF="s_setq.htm#setq"><B>setq</B></A>) <P>
<P><B>Notes:</B><P>
If <I>end-test-form</I> is <A REL=DEFINITION HREF="a_nil.htm#nil"><B>nil</B></A>, the test will never succeed. This provides an idiom for ``do forever'': the body of the <A REL=DEFINITION HREF="#do"><B>do</B></A> or <A REL=DEFINITION HREF="#doST"><B>do*</B></A> is executed repeatedly. The infinite loop can be terminated by the use of <A REL=DEFINITION HREF="m_return.htm#return"><B>return</B></A>, <A REL=DEFINITION HREF="s_ret_fr.htm#return-from"><B>return-from</B></A>, <A REL=DEFINITION HREF="s_go.htm#go"><B>go</B></A> to an outer level, or <A REL=DEFINITION HREF="s_throw.htm#throw"><B>throw</B></A>. <P>
A <A REL=DEFINITION HREF="#do"><B>do</B></A> <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> may be explained in terms of the more primitive <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>forms</I></A> <A REL=DEFINITION HREF="s_block.htm#block"><B>block</B></A>, <A REL=DEFINITION HREF="m_return.htm#return"><B>return</B></A>, <A REL=DEFINITION HREF="s_let_l.htm#let"><B>let</B></A>, <A REL=DEFINITION HREF="m_loop.htm#loop"><B>loop</B></A>, <A REL=DEFINITION HREF="s_tagbod.htm#tagbody"><B>tagbody</B></A>, and <A REL=DEFINITION HREF="m_psetq.htm#psetq"><B>psetq</B></A> as follows: <P>
<PRE>
(block nil
(let ((var1 init1)
(var2 init2)
...
(varn initn))
declarations
(loop (when end-test (return (progn . result)))
(tagbody . tagbody)
(psetq var1 step1
var2 step2
...
varn stepn))))
</PRE>
</TT> <P>
<A REL=DEFINITION HREF="#doST"><B>do*</B></A> is similar, except that <A REL=DEFINITION HREF="s_let_l.htm#letST"><B>let*</B></A> and <A REL=DEFINITION HREF="s_setq.htm#setq"><B>setq</B></A> replace the <A REL=DEFINITION HREF="s_let_l.htm#let"><B>let</B></A> and <A REL=DEFINITION HREF="m_psetq.htm#psetq"><B>psetq</B></A>, respectively. <P>
<P>
<P><HR>The following <A REL=META HREF="../Front/X3J13Iss.htm">X3J13 cleanup issues</A>, <I>not part of the specification</I>, apply to this section:<P><UL><LI> <A REL=CHILD HREF="../Issues/iss358.htm">VARIABLE-LIST-ASYMMETRY:SYMMETRIZE</A><LI> <A REL=CHILD HREF="../Issues/iss097.htm">DECLS-AND-DOC</A><P></UL><HR>
<A REL=NAVIGATOR HREF="../Front/StartPts.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Starting Points]" SRC="../Graphics/StartPts.gif" ALIGN=Bottom></A><A REL=TOC HREF="../Front/Contents.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Contents]" SRC="../Graphics/Contents.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Master.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Index]" SRC="../Graphics/Index.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Symbol.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Symbols]" SRC="../Graphics/Symbols.gif" ALIGN=Bottom></A><A REL=GLOSSARY HREF="../Body/26_a.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Glossary]" SRC="../Graphics/Glossary.gif" ALIGN=Bottom></A><A HREF="../Front/X3J13Iss.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Issues]" SRC="../Graphics/Issues.gif" ALIGN=Bottom></A><BR>
<A REL=COPYRIGHT HREF="../Front/Help.htm#Legal"><I>Copyright 1996-2005, LispWorks Ltd. All rights reserved.</I></A><P>
</BODY>
</HTML>