Previous: Accumulation Clauses, Up: Loop Facility [Contents][Index]

#### 4.7.6 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:

      (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]