Previous: Accumulation Clauses, Up: Loop Facility [Contents][Index]
This section describes the remaining loop clauses.
with var = value
This clause binds a variable to a value around the loop, but otherwise leaves the variable alone during the loop. The following loops are basically equivalent:
(cl-loop with x = 17 do …) (let ((x 17)) (cl-loop do …)) (cl-loop for x = 17 then x do …)
Naturally, the variable var might be used for some purpose in the rest of the loop. For example:
(cl-loop for x in my-list with res = nil do (push x res) finally return res)
This loop inserts the elements of my-list
at the front of
a new list being accumulated in res
, then returns the
list res
at the end of the loop. The effect is similar
to that of a collect
clause, but the list gets reversed
by virtue of the fact that elements are being pushed onto the
front of res
rather than the end.
If you omit the =
term, the variable is initialized to
nil
. (Thus the ‘= nil’ in the above example is
unnecessary.)
Bindings made by with
are sequential by default, as if
by let*
. Just like for
clauses, with
clauses
can be linked with and
to cause the bindings to be made by
let
instead.
if condition clause
This clause executes the following loop clause only if the specified
condition is true. The following clause should be an accumulation,
do
, return
, if
, or unless
clause.
Several clauses may be linked by separating them with and
.
These clauses may be followed by else
and a clause or clauses
to execute if the condition was false. The whole construct may
optionally be followed by the word end
(which may be used to
disambiguate an else
or and
in a nested if
).
The actual non-nil
value of the condition form is available
by the name it
in the “then” part. For example:
(setq funny-numbers '(6 13 -1))
⇒ (6 13 -1)
(cl-loop for x below 10
if (cl-oddp x)
collect x into odds
and if (memq x funny-numbers) return (cdr it) end
else
collect x into evens
finally return (vector odds evens))
⇒ [(1 3 5 7 9) (0 2 4 6 8)]
(setq funny-numbers '(6 7 13 -1))
⇒ (6 7 13 -1)
(cl-loop <same thing again>)
⇒ (13 -1)
Note the use of and
to put two clauses into the “then”
part, one of which is itself an if
clause. Note also that
end
, while normally optional, was necessary here to make
it clear that the else
refers to the outermost if
clause. In the first case, the loop returns a vector of lists
of the odd and even values of x. In the second case, the
odd number 7 is one of the funny-numbers
so the loop
returns early; the actual returned value is based on the result
of the memq
call.
when condition clause
This clause is just a synonym for if
.
unless condition clause
The unless
clause is just like if
except that the
sense of the condition is reversed.
named name
This clause gives a name other than nil
to the implicit
block surrounding the loop. The name is the symbol to be
used as the block name.
initially [do] forms…
This keyword introduces one or more Lisp forms which will be
executed before the loop itself begins (but after any variables
requested by for
or with
have been bound to their
initial values). initially
clauses can appear anywhere;
if there are several, they are executed in the order they appear
in the loop. The keyword do
is optional.
finally [do] forms…
This introduces Lisp forms which will be executed after the loop
finishes (say, on request of a for
or while
).
initially
and finally
clauses may appear anywhere
in the loop construct, but they are executed (in the specified
order) at the beginning or end, respectively, of the loop.
finally return form
This says that form should be executed after the loop
is done to obtain a return value. (Without this, or some other
clause like collect
or return
, the loop will simply
return nil
.) Variables bound by for
, with
,
or into
will still contain their final values when form
is executed.
do forms…
The word do
may be followed by any number of Lisp expressions
which are executed as an implicit progn
in the body of the
loop. Many of the examples in this section illustrate the use of
do
.
return form
This clause causes the loop to return immediately. The following
Lisp form is evaluated to give the return value of the loop
form. The finally
clauses, if any, are not executed.
Of course, return
is generally used inside an if
or
unless
, as its use in a top-level loop clause would mean
the loop would never get to “loop” more than once.
The clause ‘return form’ is equivalent to
‘do (cl-return form)’ (or cl-return-from
if the loop
was named). The return
clause is implemented a bit more
efficiently, though.
While there is no high-level way to add user extensions to cl-loop
,
this package does offer two properties called cl-loop-handler
and cl-loop-for-handler
which are functions to be called when a
given symbol is encountered as a top-level loop clause or for
clause, respectively. Consult the source code in file
cl-macs.el for details.
This package’s cl-loop
macro is compatible with that of Common
Lisp, except that a few features are not implemented: loop-finish
and data-type specifiers. Naturally, the for
clauses that
iterate over keymaps, overlays, intervals, frames, windows, and
buffers are Emacs-specific extensions.
Previous: Accumulation Clauses, Up: Loop Facility [Contents][Index]