Other Clauses
-------------
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:
(loop with x = 17 do ...)
(let ((x 17)) (loop do ...))
(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:
(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)
(loop for x below 10
if (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)
(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 (return FORM)' (or
`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 `loop'
(comparable to `defsetf' for `setf', say), 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 `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 which iterate over
keymaps, overlays, intervals, frames, windows, and buffers are
Emacs-specific extensions.