Structural Informatics Group (SIG) logo
Home | Projects | Demos | Downloads | Publications | Local Info | About Us | New site
Go to the first, previous, next, last section, table of contents.



type: special form (fsubr)
location: built-in
source file: xlcont.c
Common LISP compatible: yes
supported on: all machines


(do*  ( [ <binding> ... ]  ) ( <test-expr> [ <result> ] ) [ <expr> ... ]  )
        <binding>       -       a variable binding which is can take one of 
                                the following forms:
                                        ( <symbol> <init-expr> [<step-expr>] )
        <symbol>        -       a symbol
        <init-expr>     -       an initialization expression for <symbol>
        <step-expr>     -       an expression that <symbol> symbol is updated
                                at the end of each loop
        <test-expr>     -       an expression to test for loop termination 
        <result>        -       an optional expression for the returned result
        <expr>          -       expressions comprising the body of the loop
                                which may contain RETURNs, GOs or tags for GO  


The DO* special form is basically a 'while' looping construct that contains symbols (with optional initializations and updates), a loop test (with an optional return value) and a block of code (expressions) to evaluate. The DO* form evaluates its initializations and updates in sequential order (as opposed to DO which doesn't). The sequence of these events is:

<init-expr> execution
while <test-expr> do
        loop code execution
        <step-expr> execution
return <result>

The first form after the DO* is the 'binding' form. It contains a series of <symbol>'s or <binding>'s. The <binding> is a <symbol> followed by an initialization expression <init-expr> and an optional <step-expr>. If there is no <init-expr>, the <symbol> will be initialized to NIL. There is no specification as to the order of execution of the bindings or the step expressions - except that they happen all together.

The DO* form will go through and create and initialize the symbols. This is followed by evaluating the <test-expr>. If <test-expr> returns a non-NIL value, the loop will terminate. If <test-expr> returns a NIL value then the DO* will sequentially execute the <expr>'s. After execution of the loop <expr>'s, the <symbol>'s are set to the <step-expr>'s (if the <step-expr>'s exist). Then, the <test-expr> is re-evaluated, and so on.... The value of the <result> expression is evaluated and returned. If no <result> is specified, NIL is returned. When the DO* is finished execution, the <symbol>'s that were defined will no longer exist or retain their values.


(do                                     ; DO example - won't work
  ((i 0)                                ;   var I=0
     (j i) )                            ;   var J=I (won't work)
  ( (eql i j) "done")                   ;   test and result
  (print "looping"))                    ; error: unbound variable - I
(do*                                    ; DO* example - will work
  ((i 0)                                ;   var I=0
     (j i) )                            ;   var J=I (proper exec. order)
  ( (eql i j) "done")                   ;   test and result
  (print "looping"))                    ;   returns "done"
(do* (i)                                ; DO* loop with var I
  ((eql i 0) "done")                    ;   test and result
  (print i) (setq i 0) (print i))       ;   prints      NIL     0
                                        ;   returns "done"
(do* (i)                                ; DO* loop with var I
  ((eql i 0))                           ;   test but no result
  (print i) (setq i 0) (print i))       ;   prints      NIL     0
                                        ;   returns NIL
(do*                                    ; DO* loop
   ((i 0 (setq i (1+ i)))               ;   var I=0  increment by 1
    (j 10 (setq j (1- j)))      )       ;   var J=10 decrement by 1
   ((eql i j)  "met in the middle" )    ;   test and result
   (princ i) (princ " ")                ;   prints  0 10
   (princ j) (terpri))                  ;           1 9
                                        ;           2 8
                                        ;           3 7
                                        ;           4 6
                                        ;   returns "met in the middle"

Go to the first, previous, next, last section, table of contents.