Common Lisp the Language, 2nd Edition
Next: Conditional Execution
Up: Loop
Previous: Value
Accumulation
A local loop variable is one that exists only when the Loop Facility is
invoked. At that time, the variables are declared and are initialized to
some value. These local variables exist until loop iteration terminates,
at which point they cease to exist. Implicitly variables are also
established by iteration control clauses and the into
preposition of accumulation clauses.
The loop keyword with
designates a loop clause that
allows you to declare and initialize variables that are local to a loop.
The variables are initialized one time only; they can be initialized
sequentially or in parallel.
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, you can
force initializations to occur in parallel; that is, all of the
specified expressions are evaluated, and the results are bound to the
respective variables simultaneously.
Use sequential binding for making the initialization of some
variables depend on the values of previously bound variables. For
example, suppose you want to bind the variables a
,
b
, and c
in sequence:
(loop with a = 1
with b = (+ a 2)
with c = (+ b 3)
with d = (+ c 4)
return (list a b c d))
=> (1 3 6 10)
The execution of the preceding loop is equivalent to the execution of the following code:
(let* ((a 1)
(b (+ a 2))
(c (+ b 3))
(d (+ c 4)))
(block nil
(tagbody
next-loop (return (list a b c d))
(go next-loop)
end-loop)))
If you are not depending on the value of previously bound variables for the initialization of other local variables, you can use parallel bindings as follows:
(loop with a = 1
and b = 2
and c = 3
and d = 4
return (list a b c d))
=> (1 2 3 4)
The execution of the preceding loop is equivalent to the execution of the following code:
(let ((a 1)
(b 2)
(c 3)
(d 4))
(block nil
(tagbody
next-loop (return (list a b c))
(go next-loop)
end-loop)))
[Loop Clause]
with
var [type-spec]
[=
expr] {and
var [type-spec]
[=
expr]}*
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 specified for any
variable var, but there is no related expression expr
to be evaluated, var is initialized to an appropriate default
value for its data type. For example, for the data types t
,
number
, and float
, the default values are
nil
, 0
, and 0.0
, respectively. It
is an error to specify a type-spec argument for var if
the related expression returns a value that is not of the specified
type. The optional and
clause forces parallel rather than
sequential initializations.
Examples:
;;; These bindings occur in sequence.
(loop with a = 1
with b = (+ a 2)
with c = (+ b 3)
with d = (+ c 4)
return (list a b c d))
=> (1 3 6 10)
;;; These bindings occur in parallel.
(setq a 5 b 10 c 1729)
(loop with a = 1
and b = (+ a 2)
and c = (+ b 3)
and d = (+ c 4)
return (list a b c d))
=> (1 7 13 1733)
;;; This example shows a shorthand way to declare
;;; local variables that are of different types.
(loop with (a b c) (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 of the same type.
(loop with (a b c) float
return (format nil "~A ~A ~A" a b c))
=> "0.0 0.0 0.0"
Next: Conditional Execution
Up: Loop
Previous: Value
Accumulation
AI.Repository@cs.cmu.edu