Macro prog, prog*

Syntax:

prog ({var | (var [init-form])}*) {declaration}* {tag | statement}* {result}*

prog* ({var | (var [init-form])}*) {declaration}* {tag | statement}* {result}*

Arguments and Values:

var—variable name.

init-form—a form.

declaration—a declare expression; not evaluated.

tag—a go tag; not evaluated.

statement—a compound form; evaluated as described below.

resultsnil if a normal return occurs, or else, if an explicit return occurs, the values that were transferred.

Description:

7.8.5 3Three distinct operations are performed by prog and prog*: they bind local variables, they permit use of the return statement, and they permit use of the go statement. A typical prog looks like this:

 (prog (var1 var2 (var3 init-form-3) var4 (var5 init-form-5))
       {declaration}*
       statement1
  tag1
       statement2
       statement3
       statement4
  tag2
       statement5
       ...
       )

For prog, init-forms are evaluated first, in the order in which they are supplied. The vars are then bound to the corresponding values in parallel. If no init-form is supplied for a given var, that var is bound to nil.

7.8.5 11The body of prog is executed as if it were a tagbody form; the go statement can be used to transfer control to a tag. Tags label statements.

7.8.5 12prog implicitly establishes a block named nil around the entire prog form, so that return can be used at any time to exit from the prog form.

7.8.5 15The difference between prog* and prog is that in prog* the binding and initialization of the vars is done sequentially, so that the init-form for each one can use the values of previous ones.

I don't think anything in this next paragraph hasn't been stated elsewhere. --sjl 5 Mar 92 Any \param{declaration} appearing in the \macref{prog} is used as if appearing at the top of \specref{let}. It is an error if a \term{type declaration} is supplied for a \param{var} and the initial value of that \param{var} is not consistent with the \param{declaration}. Similarly, declarations in \macref{prog*} are like in \macref{let*}.

Moon: Redundant. For \macref{prog}, the \term{scope} of the name binding does not include any \param{init-form}. For \macref{prog*}, a variable's \term{scope} also includes the remaining \param{init-forms} for subsequent variable bindings.

Examples:

(prog* ((y z) (x (car y)))
       (return x))
returns the car of the value of z.

 (setq a 1) → 1
 (prog ((a 2) (b a)) (return (if (= a b) '= '/=))) → /=
 (prog* ((a 2) (b a)) (return (if (= a b) '= '/=))) → =
 (prog () 'no-return-value) → NIL
7.8.5 13
 (defun king-of-confusion (w)
   "Take a cons of two lists and make a list of conses.
    Think of this function as being like a zipper."
   (prog (x y z)          ;Initialize x, y, z to NIL
        (setq y (car w) z (cdr w))
    loop
        (cond ((null y) (return x))
              ((null z) (go err)))
    rejoin
        (setq x (cons (cons (car y) (car z)) x))
        (setq y (cdr y) z (cdr z))
        (go loop)
    err
        (cerror "Will self-pair extraneous items"
                "Mismatch - gleep!  ~S" y)
        (setq z y)
        (go rejoin))) → KING-OF-CONFUSION 
This can be accomplished more perspicuously as follows:

 (defun prince-of-clarity (w)
   "Take a cons of two lists and make a list of conses.
    Think of this function as being like a zipper."
   (do ((y (car w) (cdr y))
        (z (cdr w) (cdr z))
        (x ' () (cons (cons (car y) (car z)) x)))
       ((null y) x)
     (when (null z)
       (cerror "Will self-pair extraneous items"
              "Mismatch - gleep!  ~S" y)
       (setq z y)))) → PRINCE-OF-CLARITY 

Affected By:

None.

Exceptional Situations:

None.

See Also:

block, let, tagbody, go, return, Section 3.1 (Evaluation)

Notes:

7.8.5 14prog can be explained in terms of block, let, and tagbody as follows:

 (prog variable-list declaration . body)
    ≡ (block nil (let variable-list declaration (tagbody . body)))