loop macro performs iteration.
loop forms are partitioned into two categories: simple loop forms and extended loop forms.
A simple loop form is one that has a body containing only compound forms. 7.8.1 3Each 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. 7.8.1 4A 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).
KMP: What about LOOP-FINISH here? Test cases: (loop (loop-finish)) and (loop do (loop (loop-finish))). Mail sent to X3J13 saying I was going to make this explicitly vague, since some implementations See the LOOP-FINISH dictionary entry.
========================================
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.
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).
loop form are called clauses; the scope \reviewer{Barmar: what meaning of scope?}%!!!
of each clausethe rules for parsing are determined by the parsing ofthat 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
8Each 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.
9Loop 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.
loop macro form expands into a form containing one or more \term{lambda expressions} for the local \term{binding} of loop variablesone 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.
4After the form is expanded, it consists of three basic parts in the tagbody: the loop prologue, the loop body, and the loop epilogue.
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.
The loop body contains those forms that are executed during iteration, including application-specific calculations, termination tests, and variable stepping1.
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.
5Some 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.
6Expansion 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. Barmar: Has nothing to do with LOOP specifically.
Within the executable parts of loop clauses and around the entire
\macref{loop} form, variables can be bound by using \specref{let}.
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.
\issue{LOOP-AND-DISCREPANCY:NO-REITERATION} When two or more such clauses are joined with \loopref{and}, clauses after the first do not have \loopref{for} or \loopref{as} before them. \endissue{LOOP-AND-DISCREPANCY:NO-REITERATION}
The with construct is similar to a single let clause. with clauses can be combined using the loop keyword and to get parallel initialization.
Removed per Barmar. See Termination Clauses. The \loopref{repeat} construct causes iteration to terminate after a specified number of times. It uses an internal variable to keep track of the number of iterations.
For more information, see Section 6.1.2 (Variable Initialization and Stepping Clauses).
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).
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. Moved from text removed by Barmar above, so it doesn't get lost. -kmp 30-Jul-91(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. !!! Barmar thinks this is not necessary: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. !!! Barmar thinks this is not necessary: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.
Added per Barmar:If multiple termination test clauses are specified, the loop form terminates if any are satisfied.
Note also that the \macref{loop-finish} macro terminates iteration and returns any accumulated result. Any \loopref{finally} clauses that are supplied are evaluated.
For more information, see Section 6.1.4 (Termination Test Clauses).
do (or doing) construct evaluates all forms in its clause.
The return construct takes one \term{form} and returns its value. form. Any values returned by the form are immediately returned by the loop form. It is equivalent to the clause \f{do (return \i{value})}. 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).
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).
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. An unconditional clause can also follow \theloopkeyword{finally}.
For more information, see Section 6.1.7 (Miscellaneous Clauses).
10 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 I added this next. -kmp 10-Feb-92which transfers control to a point outside of the loop. The following actions are exceptions to the linear order of execution:
initially clauses is collected into one progn in the order in which the clauses appear in the source. The collected code is executed once in the loop prologue after any implicit variable initializations.
finally clauses is collected into one progn in the order in which the clauses appear in the source. The collected code is executed once in the loop epilogue before any implicit values from the accumulation clauses are returned. Explicit returns anywhere in the source, however, will exit the loop without executing the epilogue code.
with clause introduces a variable binding and an optional initial value. The initial values are calculated in the order in which the with clauses occur.
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:
!!! Barmar: Examples belong in the examples section
;;; 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 Replaced per Moon #42 (first public review) -kmp 6-May-93 nonstandard listsdotted 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.
loop iteration. The loop keywords for and as , and \loopref{repeat}designate iteration control clauses. Iteration control clauses differ with respect to the specification of termination tests and to the initialization and stepping1 of loop variables. Iteration clauses by themselves do not cause the Loop Facility to return values, but they can be used in conjunction with value-accumulation clauses to return values.
All variables are initialized in the loop prologue. A variable binding has lexical scope unless it is proclaimed special; thus, by default, the variable can be accessed only by forms that lie textually within the loop. Stepping assignments are made in the loop body before any other forms are evaluated in the body.
The variable argument in iteration control clauses can be a destructuring list. A destructuring list is a tree whose non-nil atoms are variable names. See Section 6.1.1.7 (Destructuring).
The iteration control clauses for, as, and repeat must precede any other loop clauses, except initially, with, and named, since they establish variable bindings. When iteration control clauses are used in a loop, Next line added for JonL:the corresponding termination tests in the loop body are evaluated before any other loop body code is executed.
If multiple iteration clauses are used to control iteration, variable initialization and stepping1 occur sequentially by default. The and construct can be used to connect two or more iteration clauses when sequential binding and stepping1 are not necessary. The iteration behavior of clauses joined by and is analogous to the behavior of the macro do with respect to do*.
The for and as clauses iterate by using one or more local loop variables that are initialized to some value and that can be modified or stepped1 after each iteration. For these clauses, iteration terminates when a local variable reaches some supplied value or when some other loop clause terminates iteration. !!! Barmar: These aren't the only ways for/as can step the variables.At each iteration, variables can be stepped1 by an increment or a decrement or can be assigned a new value by the evaluation of a form). Destructuring can be used to assign Removed per barmar--It is also used during stepping.
initialvalues to variables during iteration.
The for and as keywords are synonyms; they can be used interchangeably. There are seven syntactic formats for these constructs. In each syntactic format, the type of var can be supplied by the optional type-spec argument. If var is a destructuring list, the type supplied by the type-spec argument must appropriately match the elements of the list. !!! Barmar: "conventions" belong in the "Notes" section.By convention, for introduces new iterations and as introduces iterations that depend on a previous iteration specification.
for or as construct iterates from the value supplied by form1 to the value supplied by form2 in increments or decrements denoted by form3. Each expression is evaluated only once and must evaluate to a number. The variable var is bound to the value of form1 in the first iteration and is stepped1 by the value of form3 in each succeeding iteration, or by 1 if form3 is not provided. The following loop keywords serve as valid prepositions within this syntax. At least one of the three classes ofprepositions must be used; and at most one from each line may be used in a single subclause.
from | downfrom | upfrom
to | downto | upto | below | above
by
The prepositional phrases in each subclause may appear in any order. For example, either “from x by y” or “by y from x” is permitted. However, because left-to-right order of evaluation is preserved, the effects will be different in the case of side effects. Consider:
(let ((x 1)) (loop for i from x by (incf x) to 10 collect i)) → (1 3 5 7 9) (let ((x 1)) (loop for i by (incf x) from x to 10 collect i)) → (2 4 6 8 10)
The descriptions of the prepositions follow:
from
The loop keyword from specifies the value from which stepping1 begins, as supplied by form1. Stepping1 is incremental by default. If decremental stepping1 is desired, the preposition downto or above must be used with form2. For incremental stepping1, the default from value is 0.
downfrom, upfrom
The loop keyword downfrom indicates that the variable var is decreased in decrements supplied by form3; the loop keyword upfrom indicates that var is increased in increments supplied by form3.
to
The loop keyword to marks the end value for stepping1 supplied in form2. Stepping1 is incremental by default. If decremental stepping1 is desired, the preposition downfrom must be used with form1, or else the preposition downto or above should be used instead of to with form2.
downto, upto
The loop keyword downto specifies decremental stepping; the loop keyword upto specifies incremental stepping. In both cases, the amount of change on each step is specified by form3, and the loop terminates when the variable var passes the value of form2. Since there is no default for form1 in decremental stepping1, a form1 value must be supplied (using from or downfrom) when downto is supplied.
below, above
The loop keywords below and above are analogous to upto and downto respectively. These keywords stop iteration just before the value of the variable var reaches the value supplied by form2; the end value of form2 is not included. Since there is no default for form1 in decremental stepping1, a form1 value must be supplied (using from or downfrom) when above is supplied.
by
The loop keyword by marks the increment or decrement supplied by form3. The value of form3 can be any !!! Jonl wants to know why "positive" here.positive number. The default value is 1.
In an iteration control clause, the for or as construct causes termination when the supplied limit is reached. That is, iteration continues until the value var is stepped to the exclusive or inclusive limit supplied by form2. The range is exclusive if form3 increases or decreases var to the value of form2 without reaching that value; the loop keywords below and above provide exclusive limits. An inclusive limit allows var to attain the value of form2; to, downto, and upto provide inclusive limits.
!!! JonL wonders if we maybe shouldn't define "incremental" and "decremental" here.
;; Print some numbers.
(loop for i from 1 to 3
do (print i))
⊳ 1
⊳ 2
⊳ 3
→ NIL
;; Print every third number.
(loop for i from 10 downto 1 by 3
do (print i))
⊳ 10
⊳ 7
⊳ 4
⊳ 1
→ NIL
;; Step incrementally from the default starting value.
(loop for i below 3
do (print i))
⊳ 0
⊳ 1
⊳ 2
→ NIL
for or as construct iterates over the contents of a list. It checks for the end of the list as if by using endp. The variable var is bound to the successive elements of the list in form1 before each iteration. At the end of each iteration, the function step-fun is applied to the list; the default value for step-fun is cdr. The loop keywords in and by serve as valid prepositions in this syntax. The for or as construct causes termination when the end of the list is reached.
;; Print every item in a list.
(loop for item in '(1 2 3) do (print item))
⊳ 1
⊳ 2
⊳ 3
→ NIL
;; Print every other item in a list.
(loop for item in '(1 2 3 4 5) by #'cddr
do (print item))
⊳ 1
⊳ 3
⊳ 5
→ NIL
;; Destructure a list, and sum the x values using fixnum arithmetic.
(loop for (item . x) of-type (t . fixnum) in '((A . 1) (B . 2) (C . 3))
unless (eq item 'B) sum x)
→ 4
for or as construct iterates over the contents ofa list. It checks for the end of the list as if by using atom. The variable var is bound to the successive tails of the list in form1. At the end of each iteration, the function step-fun is applied to the list; the default value for step-fun is cdr. The loop keywords on and by serve as valid prepositions in this syntax. The for or as construct causes termination when the end of the list is reached.
;; Collect successive tails of a list.
(loop for sublist on '(a b c d)
collect sublist)
→ ((A B C D) (B C D) (C D) (D))
;; Print a list by using destructuring with the loop keyword ON.
(loop for (item) on '(1 2 3)
do (print item))
⊳ 1
⊳ 2
⊳ 3
→ NIL
for or as construct initializes the variable var by setting it to the result of evaluating form1 on the first iteration, then setting it to the result of evaluating form2 on the second and subsequent iterations. If form2 is omitted, the construct uses form1 on the second and subsequent iterations. When \param{form2} is omitted, the expanded
code shows the following optimization:The loop keywords and then serve as valid prepositions in this syntax. This construct does not provide any termination tests.
;; Collect some numbers.
(loop for item = 1 then (+ item 10)
for iteration from 1 to 5
collect item)
→ (1 11 21 31 41)
for or as construct binds the variable var to the value of each element in the array vector. The loop keyword across marks the array vector; across is used as a preposition in this syntax. Iteration stops when there are no more elements in the supplied array that can be referenced. Some implementations might recognize a the special form in the vector form to produce more efficient code.
(loop for char across (the simple-string (find-message channel))
do (write-char char stream))
for or as construct iterates over the elements, keys, and values of a hash-table. In this syntax, a compound preposition is used to designate access to a hash table. The variable var takes on the value of each hash key or hash value in the supplied hash-table. The following loop keywords serve as valid prepositions within this syntax:
being
The keyword being introduces either the Loop schema hash-key or hash-value.
each, the
The loop keyword each follows the loop keyword being when hash-key or hash-value is used. The loop keyword the is used with hash-keys and hash-values only for ease of reading. This agreement isn't required.
hash-key, hash-keys
These loop keywords access each key entry of the hash table. If the name hash-value is supplied in a using construct with one of these Loop schemas, the iteration can optionally access the keyed value. The order in which the keys are accessed is undefined; empty slots in the hash table are ignored.
hash-value, hash-values
These loop keywords access each value entry of a hash table. If the name hash-key is supplied in a using construct with one of these Loop schemas, the iteration can optionally access the key that corresponds to the value. The order in which the keys are accessed is undefined; empty slots in the hash table are ignored.
using
The loop keyword using introduces the optional key or the keyed value to be accessed. It allows access to the hash key if iteration is over the hash values, and the hash value if iteration is over the hash keys.
in, of
These loop prepositions introduce hash-table.
!!! Barmar: What does this mean?In effect
being {each | the} {hash-value | hash-values | hash-key | hash-keys} {in | of}
\code being \lbracket\ each|the\rbracket \lbracket\ hash-value|hash-values|hash-key|hash-key\rbracket \lbracket\ in|of\rbracket \endcode
is a compound preposition.
Iteration stops when there are no more hash keys or hash values to be referenced in the supplied hash-table.
for or as construct iterates over the symbols in a package. In this syntax, a compound preposition is used to designate access to a package. The variable var takes on the value of each symbol in the supplied package. The following loop keywords serve as valid prepositions within this syntax:
being
The keyword being introduces either the Loop schema symbol, present-symbol, or external-symbol.
each, the
The loop keyword each follows the loop keyword being when symbol, present-symbol, or external-symbol is used. The loop keyword the is used with symbols, present-symbols, and external-symbols only for ease of reading. This agreement isn't required.
present-symbol, present-symbols
These Loop schemas iterate over the symbols that are present in a package. but not \term{external symbols} of that \term{package}. The package to be iterated over is supplied in the same way that package arguments to find-package are supplied. If the package for the iteration is not supplied, the current package is used. If a package that does not exist is supplied, an error of type package-error is signaled.
symbol, symbols
These Loop schemas iterate over symbols that are accessible in a given package. The package to be iterated over is supplied in the same way that package arguments to find-package are supplied. If the package for the iteration is not supplied, the current package is used. If a package that does not exist is supplied, an error of type package-error is signaled.
external-symbol, external-symbols
These Loop schemas iterate over the external symbols of a package. The package to be iterated over is supplied in the same way that package arguments to find-package are supplied. If the package for the iteration is not supplied, the current package is used. If a package that does not exist is supplied, an error of type package-error is signaled.
in, of
These loop prepositions introduce package.
!!! Barmar: What does this mean?In effect
being {each | the} {symbol | symbols | present-symbol | present-symbols | external-symbol | external-symbols} {in | of}
\code being \lbracket\ each|the\rbracket \lbracket\ \lbracket\ \lbracket\ present|external\rbracket\ symbol\rbracket | \lbracket\ \lbracket\ present|external\rbracket symbols\rbracket\rbracket \lbracket\ in|of\rbracket \endcode
is a compound preposition.
Iteration stops when there are no more symbols to be referenced in the supplied package.
(let ((*package* (make-package "TEST-PACKAGE-1")))
;; For effect, intern some symbols
(read-from-string "(THIS IS A TEST)")
(export (intern "THIS"))
(loop for x being each present-symbol of *package*
do (print x)))
⊳ A
⊳ TEST
⊳ THIS
⊳ IS
→ NIL
loop form is executed, the local variables are bound and are initialized to some value. These local variables exist until loop iteration terminates, at which point they cease to exist. Implicit variables are also established by iteration control clauses and the into preposition of accumulation clauses.
The with construct initializes variables that are local to a loop. The variables are initialized one time only. If the optional type-spec argument is supplied for the variable var, but there is no related expression to be evaluated, var is initialized to an appropriate default value for its type. !!! Barmar: How is this default specified for "wierd" types? e.g.,
CLOS classes, DEFSTRUCT types, (OR ...), (AND ...), (SATISFIES ...), package, etc.For example, for the types t, number, and float, the default values are nil, 0, and 0.0 respectively. The consequences are undefined if a type-spec argument is supplied for var if the related expression returns a value that is not of the supplied type. By default, the with construct initializes variables sequentially; that is, one variable is assigned a value before the next expression is evaluated. However, by using the loop keyword and to join several with clauses, initializations can be forced to occur in parallel; that is, all of the supplied forms are evaluated, and the results are bound to the respective variables simultaneously.
The optional \loopref{and} clause forces \term{parallel} rather than \term{sequential}
initializations.Sequential binding is used when it is desireable for the initialization of some variables to depend on the values of previously bound variables. For example, suppose the variables a, b, and c are to be bound in sequence:
(loop with a = 1
with b = (+ a 2)
with c = (+ b 3)
return (list a b c))
→ (1 3 6)
The execution of the above loop is equivalent to the execution of the following code:
BLOCK moved to outside.
(block nil
(let* ((a 1)
(b (+ a 2))
(c (+ b 3)))
(tagbody
(next-loop (return (list a b c))
(go next-loop)
end-loop))))
If the values of previously bound variables are not needed for the initialization of other local variables, an and clause can be used to force the bindings to occur in \term{parallel}:
for JonL:specify that the bindings are to occur in parallel:
(loop with a = 1
and b = 2
and c = 3
return (list a b c))
→ (1 2 3)
The execution of the above loop is equivalent to the execution of the following code:
BLOCK moved to outside.
(block nil
(let ((a 1)
(b 2)
(c 3))
(tagbody
(next-loop (return (list a b c))
(go next-loop)
end-loop))))
;; These bindings occur in sequence.
(loop with a = 1
with b = (+ a 2)
with c = (+ b 3)
return (list a b c))
→ (1 3 6)
;; These bindings occur in parallel.
(setq a 5 b 10)
→ 10
(loop with a = 1
and b = (+ a 2)
and c = (+ b 3)
return (list a b c))
→ (1 7 13)
;; This example shows a shorthand way to declare local variables
;; that are of different types.
(loop with (a b c) of-type (float integer float)
return (format nil "~A ~A ~A" a b c))
→ "0.0 0 0.0"
;; This example shows a shorthand way to declare local variables
;; that are the same type.
(loop with (a b c) of-type float
return (format nil "~A ~A ~A" a b c))
→ "0.0 0.0 0.0"
!!! Moon (comment #40) thinks it would be nice to coalesce the discussion of "into" here.
The constructs collect, collecting, append, appending, nconc, nconcing, count, counting, maximize, maximizing, minimize, minimizing, sum, and summing, allow values to be accumulated in a loop.
Accumulating values during iteration and returning them from a loop is often useful. Some of these accumulations occur so frequently that special loop clauses have been developed to handle them.
The constructs collect, collecting, append, appending, nconc, and nconcing, designate clauses that accumulate values in lists and return them. The constructs count, counting, maximize, maximizing, minimize, minimizing, sum, and summing designate clauses that accumulate and return numerical values.
During each iteration, the constructs collect and collecting collect the value of the supplied form into a list. When iteration terminates, the list is returned. The argument var is set to the list of collected values; if var is supplied, the loop does not return the final list automatically. If var is not supplied, it is equivalent to supplying an internal name for var and returning its value in a finally clause. The var argument is bound as if by the construct with. A \term{type} cannot be supplied for \param{var};No mechanism is provided for declaring the type of var; it must be of type list.
Removed per Barmar. Fully redundant with next couple of paragraphs. The \loopref{append} construct is similar to \loopref{collect} except the values of the supplied \param{form} must be \term{lists}. These \term{lists} are not modified but are concatenated together into a single \term{list}, as if they were arguments to \funref{append}. The argument \param{var} is bound to the list of concatenated values; if \param{var} is supplied, the loop does not return the final \term{list} automatically. The \param{var} argument is bound as if by the construct \loopref{with}. A \term{type} cannot be supplied for \param{var}; it must be \oftype{list}.
The constructs append, appending, nconc, and nconcing are similar to collect except that the values of the supplied form must be lists.
append keyword causes its list values to be concatenated into a single list, as if they were arguments to the function append.
nconc keyword causes its list values to be concatenated into a single list, as if they were arguments to the function nconc.
The argument var is set to the list of concatenated values; if var is supplied, loop does not return the final list automatically. The var argument is bound as if by the construct with. A type cannot be supplied for var; it must be of type list. The construct nconc destructively modifies its argument lists.
Barmar: Is it required to coerce the sum to the specified type?
Test case: (loop for x in '(a b c) count x into z of-type float finally (return z))
Mail sent to Quinquevirate (issue LOOP-DECLARATION-VS-COERCION)The count construct counts the number of times that the supplied form returns true. The argument var accumulates the number of occurrences; if var is supplied, loop does not return the final count automatically. The var argument is bound as if by the construct with Per Moon #40, First Public Review. -kmp 28-Jul-93to a zero of the appropriate type. Per X3J13. -kmp 05-Oct-93Subsequent values (including any necessary coercions) are computed as if by the function 1+. If into var is used, a type can be supplied for var with the type-spec argument; the consequences are unspecified if a nonnumeric type is supplied. If there is no into variable, the optional type-spec argument applies to the internal variable that is keeping the count. The default type is implementation-dependent; but it must be Per Moon #40, First Public Review -kmp 28-Jul-93a supertype of type fixnum.
Barmar: For these next three, is type-spec a declaration, coercion, or both?
Test cases: (loop for x in '(1 2 3) minimize x into z of-type float finally (return z))
(loop for x in '(1 2 3) sum x into z of-type float finally (return z))The maximize and Per X3J13. -kmp 05-Oct-93
\loopref{minimum}minimize constructs compare the value of the supplied form obtained during the first iteration with values obtained in successive iterations. The maximum (for maximize) or minimum (for minimize) value encountered is determined Per Moon #40, First Public Review -kmp 28-Jul-93(as if by the function max for maximize and as if by the function min for minimize) and returned. Per Moon #40, First Public Review -kmp 28-Jul-93If the maximize or minimize clause is never executed, the accumulated value is unspecified. The argument var accumulates the maximum or minimum value; if var is supplied, loop does not return the maximum or minimum automatically. The var argument is bound as if by the construct with. If into var is used, a type can be supplied for var with the type-spec argument; the consequences are unspecified if a nonnumeric type is supplied. If there is no into variable, the optional type-spec argument applies to the internal variable that is keeping the maximum or minimum value. Per Moon #40, First Public Review -kmp 28-Jul-93The default type Per X3J13. -kmp 05-Oct-93is implementation-dependent; but it must be a supertype of type real.
The sum construct forms a cumulative sum of the successive primary values of the supplied form at each iteration. The argument var is used to accumulate the sum; if var is supplied, loop does not return the final sum automatically. The var argument is bound as if by the construct with Per Moon #40, First Public Review -kmp 28-Jul-93to a zero of the appropriate type. Subsequent values (including any necessary coercions) are computed as if by the function +. If into var is used, a type can be supplied for var with the type-spec argument; the consequences are unspecified if a nonnumeric type is supplied. If there is no into variable, the optional type-spec argument applies to the internal variable that is keeping the sum. Per Moon #40, First Public Review -kmp 28-Jul-93The default type Per X3J13. -kmp 05-Oct-93is implementation-dependent; but it must be a supertype of type number.
Removed per barmar. Redundant with the above.
The loop preposition \loopref{into} can be used to name the
variable used to hold partial accumulations.
The variable is bound as if by the loop
construct \loopref{with}.If into is used, the construct does not provide a default return value; however, the variable is available for use in any finally clause.
These \term{loop keywords} can also be spelled with the optional suffix {\tt ing}.
Replaced per Moon #40, First Public Review -kmp 28-Jul-93
Value-returning accumulation clauses can be combined in a \macref{loop} if
all the clauses accumulate the same \term{type} of \term{object}.
By default, the Loop Facility returns only one value;
thus, the \term{objects} collected by multiple accumulation clauses
as return values must have compatible \term{types}. For example, since both
the \loopref{collect} and \loopref{append} constructs accumulate
\term{objects} into a
\term{list} that is returned from a
\macref{loop}, they can be combined safely.Certain kinds of accumulation clauses can be combined in a loop if their destination is the same (the result of loop or an into var) because they are considered to accumulate conceptually compatible quantities. In particular, any elements of following sets of accumulation clauses can be mixed with other elements of the same set for the same destination in a loop form:
;; Collect every name and the kids in one list by using
;; COLLECT and APPEND.
(loop for name in '(fred sue alice joe june)
for kids in '((bob ken) () () (kris sunshine) ())
collect name
append kids)
→ (FRED BOB KEN SUE ALICE JOE KRIS SUNSHINE JUNE)
Per X3J13. -kmp 05-Oct-93
MultipleAny two clauses that do not accumulate the same type of object can coexist in a loop only if each clause accumulates its values into a different Removed per Barmar -- "some can still use the default" (i.e., not supply a var)
user-specifiedvariable.
Any number of values can be returned from \macref{loop} if \thefunction{values} is used, as the next example shows: \code ;; Count and collect names and ages. (loop for name in '(fred sue alice joe june) as age in '(22 26 19 20 10) append (list name age) into name-and-age-list count name into name-count sum age into total-age finally (return (values (round total-age name-count) name-and-age-list))) \EV 19, (FRED 22 SUE 26 ALICE 19 JOE 20 JUNE 10) \endcode
;; Collect all the symbols in a list.
(loop for i in '(bird 3 4 turtle (1 . 4) horse cat)
when (symbolp i) collect i)
→ (BIRD TURTLE HORSE CAT)
;; Collect and return odd numbers.
(loop for i from 1 to 10
if (oddp i) collect i)
→ (1 3 5 7 9)
;; Collect items into local variable, but don't return them.
(loop for i in '(a b c d) by #'cddr
collect i into my-list
finally (print my-list))
⊳ (A C)
→ NIL
;; Use APPEND to concatenate some sublists.
(loop for x in '((a) (b) ((c)))
append x)
→ (A B (C))
;; NCONC some sublists together. Note that only lists made by the
;; call to LIST are modified.
(loop for i upfrom 0
as x in '(a b (c))
nconc (if (evenp i) (list x) nil))
→ (A (C))
(loop for i in '(a b nil c nil d e)
count i)
→ 5
(loop for i in '(2 1 5 3 4)
maximize i)
→ 5
(loop for i in '(2 1 5 3 4)
minimize i)
→ 1
;; In this example, FIXNUM applies to the internal variable that holds
;; the maximum value.
(setq series '(1.2 4.3 5.7))
→ (1.2 4.3 5.7)
(loop for v in series
maximize (round v) of-type fixnum)
→ 6
;; In this example, FIXNUM applies to the variable RESULT.
(loop for v of-type float in series
minimize (round v) into result of-type fixnum
finally (return result))
→ 1
(loop for i of-type fixnum in '(1 2 3 4 5)
sum i)
→ 15
(setq series '(1.2 4.3 5.7))
→ (1.2 4.3 5.7)
(loop for v in series
sum (* 2.0 v))
→ 22.4
The repeat construct causes iteration to terminate after a specified number of times. The loop body executes n times, where n is the value of the expression form. The form argument is evaluated one time in the loop prologue. If the expression evaluates to 0 or to a negative number, the loop body is not evaluated.
The constructs always, never, thereis, while, until, and the macro loop-finish allow conditional termination of iteration within a loop.
The constructs always, never, and thereis provide specific values to be returned when a loop terminates. Using always, never, or thereis in a loop with value accumulation clauses that are not into causes an error of type program-error to be signaled (at macro expansion time). Since always, never, and thereis use the return-from special operator to terminate iteration, any finally clause that is supplied is not evaluated Added for JonLwhen exit occurs due to any of these constructs. In all other respects these constructs behave like the while and until constructs.
The always construct takes one form and terminates the loop if the form ever evaluates to nil; in this case, it returns nil. Otherwise, it provides a default return value of t. If the value of the supplied form is never nil, some other construct can terminate the iteration.
The {\tt never} construct takes one
\term{form} and terminates the \macref{loop}
if the \term{form} ever evaluates to \term{non-nil}; in this case, it returns
\nil. Otherwise, it provides a default return value of {\tt t}.The never construct terminates iteration the first time that the value of the supplied form is non-nil; the loop returns nil. If the value of the supplied form is always nil, some other construct can terminate the iteration. Unless some other clause contributes a return value, the default value returned is t.
The {\tt thereis} construct takes one \param{form} and terminates the
\macref{loop}
if the \param{form} ever evaluates to \term{non-nil}; in this case, it returns
that value.The thereis construct terminates iteration the first time that the value of the supplied form is non-nil; the loop returns the value of the supplied form. If the value of the supplied form is always nil, some other construct can terminate the iteration. Unless some other clause contributes a return value, the default value returned is nil.
!!! Barmar: Combine this differences info with never/until below.There are two differences between the thereis and until constructs:
until construct does not return a value or nil based on the value of the supplied form.
until construct executes any finally clause. Since thereis uses the return-from special operator to terminate iteration, any finally clause that is supplied is not evaluated Added per JonLwhen exit occurs due to thereis.
The while construct allows iteration to continue until the supplied form evaluates to false. The supplied form is reevaluated at the location of the while clause.
The until construct is equivalent to while (not form)…. If the value of the supplied form is non-nil, iteration terminates.
Removed per X3J13. -kmp 4-Oct-93
The \loopref{while} and \loopref{until} constructs can be used
at any point in a \macref{loop}.
Next two lines (sentences) moved from farther down per X3J13. -kmp 4-Oct-93Termination-test control constructs can be used anywhere within the loop body. The termination tests are used in the order in which they appear. If an until or while clause causes termination, any clauses that precede it in the source are still evaluated. If the until and while constructs cause termination, control is passed to the loop epilogue, where any finally clauses will be executed.
There are two differences between the never and until constructs:
until construct does not return t or nil based on the value of the supplied form.
until construct executes any \loopref{finally} clause.does not bypass any finally clauses. Since never uses the return-from special operator to terminate iteration, any finally clause that is supplied is not evaluated Added per JonLwhen exit occurs due to never. The macro \macref{loop-finish} can be used at any time to cause normal termination.
The macro \macref{loop-finish} terminates iteration normally and returns any accumulated result. If specified, a {\tt finally} clause is evaluated.
In most cases it is not necessary to use loop-finish because other loop control clauses terminate the loop. The macro loop-finish is used to provide a normal exit from a nested conditional inside a loop. You can use \macref{loop-finish}
inside nested Lisp code to provide a normal exit from a loop.
Removed per X3J13. -kmp 05-Oct-93
In normal termination, \loopref{finally} clauses are
executed and default return values are returned.Since loop-finish transfers control to the loop epilogue, using loop-finish within a finally expression can cause infinite looping. This information is already available in the macro entry for LOOP-FINISH.
Implementations are allowed to provide \macref{loop-finish}
as a local macro
by using \specref{macrolet}.
It is \term{implementation-dependent} whether or not,
in a particular \macref{loop} invocation, \macref{loop-finish}
is implemented as a global \term{macro} or a local one (created as if by \specref{macrolet}).
(loop repeat 3
do (format t "~&What I say three times is true.~%"))
⊳ What I say three times is true.
⊳ What I say three times is true.
⊳ What I say three times is true.
→ NIL
(loop repeat -15
do (format t "What you see is what you expect~%"))
→ NIL
;; Make sure I is always less than 11 (two ways).
;; The FOR construct terminates these loops.
(loop for i from 0 to 10
always (< i 11))
→ T
(loop for i from 0 to 10
never (> i 11))
→ T
;; If I exceeds 10 return I; otherwise, return NIL.
;; The THEREIS construct terminates this loop.
(loop for i from 0
thereis (when (> i 10) i) )
→ 11
;;; The FINALLY clause is not evaluated in these examples.
(loop for i from 0 to 10
always (< i 9)
finally (print "you won't see this"))
→ NIL
(loop never t
finally (print "you won't see this"))
→ NIL
(loop thereis "Here is my value"
finally (print "you won't see this"))
→ "Here is my value"
;; The FOR construct terminates this loop, so the FINALLY clause
;; is evaluated.
(loop for i from 1 to 10
thereis (> i 11)
finally (prin1 'got-here))
⊳ GOT-HERE
→ NIL
;; If this code could be used to find a counterexample to Fermat's
;; last theorem, it would still not return the value of the
;; counterexample because all of the THEREIS clauses in this example
;; only return T. But if Fermat is right, that won't matter
;; because this won't terminate.
(loop for z upfrom 2
thereis
(loop for n upfrom 3 below (log z 2)
thereis
(loop for x below z
thereis
(loop for y below z
thereis (= (+ (expt x n) (expt y n))
(expt z n))))))
(loop while (hungry-p) do (eat))
;; UNTIL NOT is equivalent to WHILE.
(loop until (not (hungry-p)) do (eat))
;; Collect the length and the items of STACK.
(let ((stack '(a b c d e f)))
(loop for item = (length stack) then (pop stack)
collect item
while stack))
→ (6 A B C D E F)
;; Use WHILE to terminate a loop that otherwise wouldn't terminate.
;; Note that WHILE occurs after the WHEN.
(loop for i fixnum from 3
when (oddp i) collect i
while (< i 5))
→ (3 5)
The do and doing constructs evaluate the supplied forms wherever they occur in the expanded form of loop. The form argument can be any compound form. Each form is evaluated in every iteration. Because every loop clause must begin with a loop keyword, the keyword do is used when no control action other than execution is required.
!!! This was said somewhere already. -kmp 12-May-91 The \loopref{return} construct takes one \term{form} and returns its \term{values}. 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 \f{do (return \i{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.
;; Print numbers and their squares.
;; The DO construct applies to multiple forms.
(loop for i from 1 to 3
do (print i)
(print (* i i)))
⊳ 1
⊳ 1
⊳ 2
⊳ 4
⊳ 3
⊳ 9
→ NIL
The \loopref{if}, \loopref{when}, and \loopref{unless} constructs establish conditional control in a \macref{loop}. If the supplied condition is \term{true}, the succeeding loop clause is executed. If the supplied condition is not true, the succeeding clause is skipped, and program control moves to the clause that follows the \term{loop keyword} \loopref{else}. If the supplied condition is not true and no \loopref{else} clause is supplied, control is transferred to the clause or construct following the supplied condition. the entire conditional construct is skipped. The constructs \loopref{if} and \loopref{when} allow execution of loop clauses conditionally. These constructs are synonyms and can be used interchangeably. If the value of the test expression \param{form} is \term{non-nil}, the expression \param{clause1} is evaluated. If the test expression evaluates to \nil\ and an \loopref{else} construct is supplied, the \term{forms} that follow the \loopref{else} are evaluated; otherwise, control passes to the next clause. If \loopref{if} or \loopref{when} clauses are nested, each \loopref{else} is paired with the closest preceding \loopref{if} or \loopref{when} construct that has no associated \loopref{else} or \loopref{end}. The \loopref{unless} construct is equivalent to \f{when (not \param{form})} and \f{if (not \param{form})}. If the value of the test expression \param{form} is \nil, the expression \param{clause1} is evaluated. If the test expression evaluates to \term{non-nil} and an \loopref{else} construct is supplied, the statements that follow the \loopref{else} are evaluated; otherwise, no conditional statement is evaluated. The \param{clause} arguments must be either accumulation, unconditional, or conditional clauses.
The if, when, and unless constructs establish conditional control in a loop. If the test passes, the succeeding loop clause is executed. If the test does not pass, the succeeding clause is skipped, and program control moves to the clause that follows the loop keyword else. If the test does not pass and no else clause is supplied, control is transferred to the clause or construct following the entire conditional clause.
If conditional clauses are nested, each else is paired with the closest preceding conditional clause that has no associated else or end.
In the if and when clauses, which are synonymous, the test passes if the value of form is true.
Per X3J13. -kmp 05-Oct-93
The \loopref{unless} \param{form} construct
is equivalent to \f{when (not \param{form})};
the test passes if the value of \param{form} is \term{false}.In the unless clause, the test passes if the value of form is false.
Clauses that follow the test expression can be grouped by using the loop keyword and to produce a conditional block consisting of a compound clause.
The \term{loop keyword} \loopref{it} can be used to refer to the result of the
test expression in a clause. If multiple clauses are connected
with \loopref{and},
the \loopref{it} construct must be in the first clause in the block. Since \loopref{it}
is a \term{loop keyword}, \loopref{it} cannot be used as a local variable within
\macref{loop}.The loop keyword it can be used to refer to the result of the test expression in a clause. Use the loop keyword it in place of the form in a return clause or an accumulation clause that is inside a conditional execution clause. If multiple clauses are connected with and, the it construct must be in the first clause in the block.
The optional loop keyword end marks the end of the clause. If this keyword is not supplied, the next loop keyword marks the end. The construct end can be used to distinguish the scoping of compound clauses.
;; Signal an exceptional condition.
(loop for item in '(1 2 3 a 4 5)
when (not (numberp item))
return (cerror "enter new value" "non-numeric value: ~s" item))
Error: non-numeric value: A
;; The previous example is equivalent to the following one.
(loop for item in '(1 2 3 a 4 5)
when (not (numberp item))
do (return
(cerror "Enter new value" "non-numeric value: ~s" item)))
Error: non-numeric value: A
Removed ";; The FINALLY clause prints the last value of I." per X3J13. -kmp 05-Oct-93
;; This example parses a simple printed string representation from
;; BUFFER (which is itself a string) and returns the index of the
;; closing double-quote character.
(let ((buffer "\"a\" \"b\""))
(loop initially (unless (char= (char buffer 0) #\")
(loop-finish))
for i of-type fixnum from 1 below (length (the string buffer))
when (char= (char buffer i) #\")
return i))
→ 2
;; The collected value is returned.
(loop for i from 1 to 10
when (> i 5)
collect i
finally (prin1 'got-here))
⊳ GOT-HERE
→ (6 7 8 9 10)
;; Return both the count of collected numbers and the numbers.
(loop for i from 1 to 10
when (> i 5)
collect i into number-list
and count i into number-count
finally (return (values number-count number-list)))
→ 5, (6 7 8 9 10)
named construct establishes a name for an implicit block surrounding the entire loop so that the return-from special operator can be used to return values from or to exit loop. Only one name per loop form can be assigned. If used, the named construct must be the first clause in the loop expression.
!!! This is said already above (twice). Consolidate? -kmp 29-Apr-93 The return construct takes one form. Any values returned by the form are immediately returned by the loop form. This construct is similar to the return-from special operator and the return macro. The Loop Facility supports the \loopref{return} construct for backwards
compatibility with older loop implementations.The return construct returns immediately and does not execute any finally clause that the loop form is given.
;; Just name and return.
(loop named max
for i from 1 to 10
do (print i)
do (return-from max 'done))
⊳ 1
→ DONE
initially and finally constructs evaluate forms that occur before and after the loop body.
The initially construct causes the supplied Per X3J13. -kmp 05-Oct-93
\param{form}compound-forms to be evaluated in the loop prologue, which precedes all loop code except for initial settings supplied by constructs with, for, or as. The code for any initially clauses is "collected into one \specref{progn}" => "executed" per barmar:
They don't have to be collected into a real PROGN since the LOOP expands into a TAGBODY.
-kmp 31-Jul-91executed in the order in which the clauses appeared in the loop. The collected code is executed once in the loop prologue
after any implicit variable initializations.
Removed per X3J13. -kmp 05-Oct-93
The \param{form} argument can be any \term{compound form}.
The finally construct causes the supplied Per X3J13. -kmp 05-Oct-93
\param{form}compound-forms to be evaluated in the loop epilogue after normal iteration terminates. The code for any finally clauses is collected into one \specref{progn}executed in the order in which the clauses appeared in the loop. The collected code is executed once in the loop epilogue before any implicit values are returned from the accumulation clauses. Explicit \macref{return} \term{forms} inAn explicit transfer of control (e.g., by return, go, or throw) from the loop body, however, will exit the loop without executing the epilogue code. Removed per X3J13. -kmp 05-Oct-93
The \param{form} argument can be any \term{compound form}.
Clauses such as return, always, never, and thereis can bypass the finally clause. return (or return-from, if the named option was supplied) can be used after finally to return values from a loop. The evaluation of the \macref{return} formSuch an explicit return inside the finally clause takes precedence over returning the accumulation from clauses supplied by such keywords as collect, nconc, append, sum, count, maximize, and minimize; the accumulation values for these preempted clauses are not returned by loop if return or return-from is used.
Clauses such as {\tt return}, {\tt always}, {\tt never}, and {\tt thereis} defeat the {\tt finally} clause.
Removed per Barmar: Said much earlier. The constructs \loopref{do}, \loopref{initially}, and \loopref{finally} are the only \term{loop keywords} that take an arbitrary number of \term{forms} and group them as if by using an \term{implicit progn}.
(let ((i 0)) ; no loop keywords are used
(loop (incf i) (if (= i 3) (return i)))) → 3
(let ((i 0)(j 0))
(tagbody
(loop (incf j 3) (incf i) (if (= i 3) (go exit)))
exit)
j) → 9
In the following example, the variable x is stepped before y is stepped; thus, the value of y reflects the updated value of x:
(loop for x from 1 to 10
for y = nil then x
collect (list x y))
→ ((1 NIL) (2 2) (3 3) (4 4) (5 5) (6 6) (7 7) (8 8) (9 9) (10 10))
In this example, x and y are stepped in parallel:
(loop for x from 1 to 10
and y = nil then x
collect (list x y))
→ ((1 NIL) (2 1) (3 2) (4 3) (5 4) (6 5) (7 6) (8 7) (9 8) (10 9))
;; Group conditional clauses.
(loop for i in '(1 324 2345 323 2 4 235 252)
when (oddp i)
do (print i)
and collect i into odd-numbers
and do (terpri)
else ; I is even.
collect i into even-numbers
finally
(return (values odd-numbers even-numbers)))
⊳ 1
⊳
⊳ 2345
⊳
⊳ 323
⊳
⊳ 235
→ (1 2345 323 235), (324 2 4 252)
;; Collect numbers larger than 3.
(loop for i in '(1 2 3 4 5 6)
when (and (> i 3) i)
collect it) ; IT refers to (and (> i 3) i).
→ (4 5 6)
;; Find a number in a list.
(loop for i in '(1 2 3 4 5 6)
when (and (> i 3) i)
return it)
→ 4
;; The above example is similar to the following one.
(loop for i in '(1 2 3 4 5 6)
thereis (and (> i 3) i))
→ 4
;; Nest conditional clauses.
(let ((list '(0 3.0 apple 4 5 9.8 orange banana)))
(loop for i in list
when (numberp i)
when (floatp i)
collect i into float-numbers
else ; Not (floatp i)
collect i into other-numbers
else ; Not (numberp i)
when (symbolp i)
collect i into symbol-list
else ; Not (symbolp i)
do (error "found a funny value in list ~S, value ~S~%" list i)
finally (return (values float-numbers other-numbers symbol-list))))
→ (3.0 9.8), (0 4 5), (APPLE ORANGE BANANA)
;; Without the END preposition, the last AND would apply to the
;; inner IF rather than the outer one.
(loop for x from 0 to 3
do (print x)
if (zerop (mod x 2))
do (princ " a")
and if (zerop (floor x 2))
do (princ " b")
end
and do (princ " c"))
⊳ 0 a b c
⊳ 1
⊳ 2 a c
⊳ 3
→ NIL
The clause repeat n ... is roughly equivalent to a clause such as
(loop for internal-variable downfrom (- n 1) to 0 ...)
but in some implementations, the repeat construct might be more efficient.
Within the executable parts of the loop clauses and around the entire loop form, variables can be bound by using let.
Use caution when using a variable named IT (in any package) in connection with loop, since it is a loop keyword that can be used in place of a form in certain contexts.
There is currently no specified portable no standardized mechanism for users to add extensions to loop. The names \f{defloop} and \f{define-loop-method}
have been suggested as candidates for such a method.
do, do* Macrodotimes Macrodolist Macroloop Macroloop-finish Local Macro