Conditionals in Elisp's cl-loop facility

continue, elisp, lisp, loops

Solution

In Common Lisp it is not possible to write such a LOOP. See the LOOP Syntax.

There is a set of variable clauses on the top. But you can't use one like `FOR` later in the main clause. So in an `IF` clause you can't use `FOR`. If you want to introduce a local variable, then you need to introduce it at the top as a `WITH` clause and set it later in the body.

(loop for i in '(1 2 3)
      with x
      if (evenp i)
        append (list)
      else
        do (setf x (* i i))
        and append (list x))

`LOOP` in Common Lisp also has no `continue` feature. One would use a conditional clause.

Note, that Common Lisp has a more advanced iteration construct as a library `ITERATE`. It does not exist for Emacs Lisp, though.

Problem

I'm trying to wrap my head around Elisp's cl-loop facility but can't seem to find a way to skip elements. Here's an artificial example to illustrate the problem: I'd like to loop over a list of integers and get a new list in which all odd integers from the original list are squared. The even integers should be omitted. According to the documentation of cl-loop, I should be able to do this: ``` (loop for i in '(1 2 3) if (evenp i) append (list) else for x = (* x x) and append (list x)) ``` The desired output is `'(1 9)` instead I get an error: ``` cl--parse-loop-clause: Expected a `for' preposition, found (list x) ``` Apparently the `and` doesn't work as expected but I don't understand why. (I'm aware that I could simplify the else block to consist of only one clause such that the `and` isn't needed anymore. However, I'm interested in situations where you really have to connect several clauses with `and`.) Second part of the question: Ideally, I would be able to write this: ``` (loop for i in '(1 2 3) if (evenp i) continue for x = (* x x) append (list x)) ``` Continue is a very common way to skip iterations in other languages. Why doesn't cl-loop have a continue operator? Is there a simple way to skip elements that I overlooked (simpler than what I tried in the first example)?

Original source