Next: , Up: The LOOP Facility


6.1.1 Overview of the Loop Facility

The loop macro performs iteration.

6.1.1.1 Simple vs Extended Loop

loop forms are partitioned into two categories: simple loop forms and extended loop forms.

6.1.1.1.1 Simple Loop

A simple loop form is one that has a body containing only compound forms. Each form is evaluated in turn from left to right. When the last form has been evaluated, then the first form is evaluated again, and so on, in a never-ending cycle. A simple loop form establishes an implicit block named nil. The execution of a simple loop can be terminated by explicitly transfering control to the implicit block (using return or return-from) or to some exit point outside of the block (e.g., using throw, go, or return-from).

6.1.1.1.2 Extended Loop

An extended loop form is one that has a body containing atomic expressions. When the loop macro processes such a form, it invokes a facility that is commonly called “the Loop Facility.”

The Loop Facility provides standardized access to mechanisms commonly used in iterations through Loop schemas, which are introduced by loop keywords.

The body of an extended loop form is divided into loop clauses, each which is in turn made up of loop keywords and forms.

6.1.1.2 Loop Keywords

Loop keywords are not true keywords1; they are special symbols, recognized by name rather than object identity, that are meaningful only to the loop facility. A loop keyword is a symbol but is recognized by its name (not its identity), regardless of the packages in which it is accessible.

In general, loop keywords are not external symbols of the COMMON-LISP package, except in the coincidental situation that a symbol with the same name as a loop keyword was needed for some other purpose in Common Lisp. For example, there is a symbol in the COMMON-LISP package whose name is "UNLESS" but not one whose name is "UNTIL".

If no loop keywords are supplied in a loop form, the Loop Facility executes the loop body repeatedly; see Section 6.1.1.1.1 (Simple Loop).

6.1.1.3 Parsing Loop Clauses

The syntactic parts of an extended loop form are called clauses; the rules for parsing are determined by that clause's keyword. The following example shows a loop form with six clauses:

 (loop for i from 1 to (compute-top-value)       ; first clause
       while (not (unacceptable i))              ; second clause
       collect (square i)                        ; third clause
       do (format t "Working on ~D now" i)       ; fourth clause
       when (evenp i)                            ; fifth clause
         do (format t "~D is a non-odd number" i)
       finally (format t "About to exit!"))      ; sixth clause

Each loop keyword introduces either a compound loop clause or a simple loop clause that can consist of a loop keyword followed by a single form. The number of forms in a clause is determined by the loop keyword that begins the clause and by the auxiliary keywords in the clause. The keywords do, doing, initially, and finally are the only loop keywords that can take any number of forms and group them as an implicit progn.

Loop clauses can contain auxiliary keywords, which are sometimes called prepositions. For example, the first clause in the code above includes the prepositions from and to, which mark the value from which stepping begins and the value at which stepping ends.

For detailed information about loop syntax, see the macro loop.

6.1.1.4 Expanding Loop Forms

A loop macro form expands into a form containing one or more binding forms (that establish bindings of loop variables) and a block and a tagbody (that express a looping control structure). The variables established in loop are bound as if by let or lambda.

Implementations can interleave the setting of initial values with the bindings. However, the assignment of the initial values is always calculated in the order specified by the user. A variable is thus sometimes bound to a meaningless value of the correct type, and then later in the prologue it is set to the true initial value by using setq. One implication of this interleaving is that it is implementation-dependent whether the lexical environment in which the initial value forms (variously called the form1, form2, form3, step-fun, vector, hash-table, and package) in any for-as-subclause, except for-as-equals-then, are evaluated includes only the loop variables preceding that form or includes more or all of the loop variables; the form1 and form2 in a for-as-equals-then form includes the lexical environment of all the loop variables.

After the form is expanded, it consists of three basic parts in the tagbody: the loop prologue, the loop body, and the loop epilogue.

Loop prologue

The loop prologue contains forms that are executed before iteration begins, such as any automatic variable initializations prescribed by the variable clauses, along with any initially clauses in the order they appear in the source.

Loop body

The loop body contains those forms that are executed during iteration, including application-specific calculations, termination tests, and variable stepping1.

Loop epilogue

The loop epilogue contains forms that are executed after iteration terminates, such as finally clauses, if any, along with any implicit return value from an accumulation clause or an termination-test clause.

Some clauses from the source form contribute code only to the loop prologue; these clauses must come before other clauses that are in the main body of the loop form. Others contribute code only to the loop epilogue. All other clauses contribute to the final translated form in the same order given in the original source form of the loop.

Expansion of the loop macro produces an implicit block named nil  unless named is supplied. Thus, return-from (and sometimes return) can be used to return values from loop or to exit loop.

6.1.1.5 Summary of Loop Clauses

Loop clauses fall into one of the following categories:

6.1.1.5.1 Summary of Variable Initialization and Stepping Clauses

The for and as constructs provide iteration control clauses that establish a variable to be initialized. for and as clauses can be combined with the loop keyword and to get parallel initialization and stepping1. Otherwise, the initialization and stepping1 are sequential.

The with construct is similar to a single let clause. with clauses can be combined using the loop keyword and to get parallel initialization.

For more information, see Section 6.1.2 (Variable Initialization and Stepping Clauses).

6.1.1.5.2 Summary of Value Accumulation Clauses

The collect (or collecting) construct takes one form in its clause and adds the value of that form to the end of a list of values. By default, the list of values is returned when the loop finishes.

The append (or appending) construct takes one form in its clause and appends the value of that form to the end of a list of values. By default, the list of values is returned when the loop finishes.

The nconc (or nconcing) construct is similar to the append construct, but its list values are concatenated as if by the function nconc. By default, the list of values is returned when the loop finishes.

The sum (or summing) construct takes one form in its clause that must evaluate to a number and accumulates the sum of all these numbers. By default, the cumulative sum is returned when the loop finishes.

The count (or counting) construct takes one form in its clause and counts the number of times that the form evaluates to true. By default, the count is returned when the loop finishes.

The minimize (or minimizing) construct takes one form in its clause and determines the minimum value obtained by evaluating that form. By default, the minimum value is returned when the loop finishes.

The maximize (or maximizing) construct takes one form in its clause and determines the maximum value obtained by evaluating that form. By default, the maximum value is returned when the loop finishes.

For more information, see Section 6.1.3 (Value Accumulation Clauses).

6.1.1.5.3 Summary of Termination Test Clauses

The for and as constructs provide a termination test that is determined by the iteration control clause.

The repeat construct causes termination after a specified number of iterations. (It uses an internal variable to keep track of the number of iterations.)

The while construct takes one form, a test, and terminates the iteration if the test evaluates to false. A while clause is equivalent to the expression (if (not test) (loop-finish)).

The until construct is the inverse of while; it terminates the iteration if the test evaluates to any non-nil value. An until clause is equivalent to the expression (if test (loop-finish)).

The always construct takes one form and terminates the loop if the form ever evaluates to false; in this case, the loop form returns nil. Otherwise, it provides a default return value of t.

The never construct takes one form and terminates the loop if the form ever evaluates to true; in this case, the loop form returns nil. Otherwise, it provides a default return value of t.

The thereis construct takes one form and terminates the loop if the form ever evaluates to a non-nil object; in this case, the loop form returns that object. Otherwise, it provides a default return value of nil.

If multiple termination test clauses are specified, the loop form terminates if any are satisfied.

For more information, see Section 6.1.4 (Termination Test Clauses).

6.1.1.5.4 Summary of Unconditional Execution Clauses

The do (or doing) construct evaluates all forms in its clause.

The return construct takes one form. Any values returned by the form are immediately returned by the loop form. It is equivalent to the clause do (return-from block-name value), where block-name is the name specified in a named clause, or nil if there is no named clause.

For more information, see Section 6.1.5 (Unconditional Execution Clauses).

6.1.1.5.5 Summary of Conditional Execution Clauses

The if and when constructs take one form as a test and a clause that is executed when the test yields true. The clause can be a value accumulation, unconditional, or another conditional clause; it can also be any combination of such clauses connected by the loop and keyword.

The loop unless construct is similar to the loop when construct except that it complements the test result.

The loop else construct provides an optional component of if, when, and unless clauses that is executed when an if or when test yields false or when an unless test yields true. The component is one of the clauses described under if.

The loop end construct provides an optional component to mark the end of a conditional clause.

For more information, see Section 6.1.6 (Conditional Execution Clauses).

6.1.1.5.6 Summary of Miscellaneous Clauses

The loop named construct gives a name for the block of the loop.

The loop initially construct causes its forms to be evaluated in the loop prologue, which precedes all loop code except for initial settings supplied by the constructs with, for, or as.

The loop finally construct causes its forms to be evaluated in the loop epilogue after normal iteration terminates.

For more information, see Section 6.1.7 (Miscellaneous Clauses).

6.1.1.6 Order of Execution

With the exceptions listed below, clauses are executed in the loop body in the order in which they appear in the source. Execution is repeated until a clause terminates the loop or until a return, go, or throw form is encountered which transfers control to a point outside of the loop. The following actions are exceptions to the linear order of execution:

6.1.1.7 Destructuring

The d-type-spec argument is used for destructuring. If the d-type-spec argument consists solely of the type fixnum, float, t, or nil, the of-type keyword is optional. The of-type construct is optional in these cases to provide backwards compatibility; thus, the following two expressions are the same:

;;; This expression uses the old syntax for type specifiers.
 (loop for i fixnum upfrom 3 ...)

;;; This expression uses the new syntax for type specifiers.
 (loop for i of-type fixnum upfrom 3 ...)

;; Declare X and Y to be of type VECTOR and FIXNUM respectively.
 (loop for (x y) of-type (vector fixnum)
       in l do ...)

A type specifier for a destructuring pattern is a tree of type specifiers with the same shape as the tree of variable names, with the following exceptions:

Destructuring allows binding of a set of variables to a corresponding set of values anywhere that a value can normally be bound to a single variable. During loop expansion, each variable in the variable list is matched with the values in the values list. If there are more variables in the variable list than there are values in the values list, the remaining variables are given a value of nil. If there are more values than variables listed, the extra values are discarded.

To assign values from a list to the variables a, b, and c, the for clause could be used to bind the variable numlist to the car of the supplied form, and then another for clause could be used to bind the variables a, b, and c sequentially.

;; Collect values by using FOR constructs.
 (loop for numlist in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
       for a of-type integer = (first numlist)
       and b of-type integer = (second numlist)
       and c of-type float = (third numlist)
       collect (list c b a))
 ((4.0 2 1) (8.3 6 5) (10.4 9 8))

Destructuring makes this process easier by allowing the variables to be bound in each loop iteration. Types can be declared by using a list of type-spec arguments. If all the types are the same, a shorthand destructuring syntax can be used, as the second example illustrates.

;; Destructuring simplifies the process.
 (loop for (a b c) of-type (integer integer float) in
       '((1 2 4.0) (5 6 8.3) (8 9 10.4))
       collect (list c b a))
 ((4.0 2 1) (8.3 6 5) (10.4 9 8))


;; If all the types are the same, this way is even simpler.
 (loop for (a b c) of-type float in
       '((1.0 2.0 4.0) (5.0 6.0 8.3) (8.0 9.0 10.4))
       collect (list c b a))
 ((4.0 2.0 1.0) (8.3 6.0 5.0) (10.4 9.0 8.0))

If destructuring is used to declare or initialize a number of groups of variables into types, the loop keyword and can be used to simplify the process further.

;; Initialize and declare variables in parallel by using the AND construct.
 (loop with (a b) of-type float = '(1.0 2.0)
       and (c d) of-type integer = '(3 4)
       and (e f)
       return (list a b c d e f))
 (1.0 2.0 3 4 NIL NIL)

If nil is used in a destructuring list, no variable is provided for its place.

 (loop for (a nil b) = '(1 2 3)
       do (return (list a b)))
 (1 3)

Note that dotted lists can specify destructuring.

 (loop for (x . y) = '(1 . 2)
       do (return y))
 2
 (loop for ((a . b) (c . d)) of-type ((float . float) (integer . integer)) in
       '(((1.2 . 2.4) (3 . 4)) ((3.4 . 4.6) (5 . 6)))
       collect (list a b c d))
 ((1.2 2.4 3 4) (3.4 4.6 5 6))

An error of type program-error is signaled (at macro expansion time) if the same variable is bound twice in any variable-binding clause of a single loop expression. Such variables include local variables, iteration control variables, and variables found by destructuring.

6.1.1.8 Restrictions on Side-Effects

See Section 3.6 (Traversal Rules and Side Effects).