GNU Info

Info Node: (librep.info)Looping Structures

(librep.info)Looping Structures


Next: Non-Local Exits Prev: Conditional Structures Up: Control Structures
Enter node , (file) or (file)node

Looping Structures
------------------

   The `librep' Lisp dialect only has one method of creating looping
control structures--recursion. Any looping construct found in an
imperative language can be represented as a recursive function. For
example the common `while' statement:

     (while CONDITION BODY...)
     ==
     (letrec ((loop (lambda ()
                      (when CONDITION
                        BODY
                        (loop)))))
       (loop))

Each successive iteration of the loop is simply another call to the
function. Also note that the recursive call to the `(loop)' function
occurs in the tail-position of the function. When combined with the
system's ability to eliminate tail-calls (Note: Function Call Forms)
the above example loop has bounded space requirements. This is
important when loops make a large number of iterations.

   Although tail-recursion is the only primitive method of looping, the
language offers a number of looping forms for convenience.

 - Macro: do vars (test expr...) body...
     `do' is an iteration construct; VARS specifies a set of variable
     bindings to be created, how they are initialized and how they are
     updated on each iteration. TEST specifies the termination
     condition of the loop, any EXPR... forms are evaluated immediately
     prior to exiting the `do' construct. The BODY...  forms specify
     the side effecting body of the loop.

     VARS is a list of variable clauses, each of which has the
     structure `(VARIABLE INIT STEP)' where VARIABLE is the name of a
     variable, INIT defines the initial value of its binding, and STEP
     defines how the next value of the binding is computed. An
     alternative form is `(VARIABLE INIT)', in this case the value of
     the binding does not change across loop iterations.

     Each iteration begins by evaluating TEST, if the result is false,
     then the BODY... expressions are evaluated, and the variables
     bound to new locations initialized to the results of evaluating
     the associated STEP forms.

     If the result of evaluating TEST is true then the EXPR... forms
     are evaluated, and the `do' construct returns the value of the
     last EXPR form evaluated.

          (do ((vec (make-vector 5))
               (i 0 (1+ i)))
              ((= i 5) vec)
            (aset vec i i))
          
              => [0 1 2 3 4]

   The "named-let" variant of the `let' form also provides a convenient
looping construct.

 - Macro: let variable bindings body...
     This is the same as the `(let BINDINGS BODY...)' form described in
     Note: Local Variables, but within the BODY... forms, the symbol
     VARIABLE is bound to a function whose parameters are the bound
     variables defined by BINDINGS and whose body is the sequence of
     forms BODY...

     This means that the body of the `let' may be repeated by invoking
     the function VARIABLE with suitable parameters.

          (let loop ((rest '(1 2 3))
                     (total 0))
            (if (null rest)
                total
              (loop (cdr rest) (+ total (car rest)))))
          
              => 6

   Finally, the imperative `while' form shown at the start of the
section is also provided:

 - Macro: while condition body...
     The CONDITION form is evaluated. If it is true an implicit progn
     is performed on the BODY forms and the whole procedure is repeated.

     This continues until the CONDITION form evaluates to false.  The
     value of every `while' structure that terminates is false.


automatically generated by info2www version 1.2.2.9