Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditionals in Elisp's cl-loop facility

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)?

like image 551
tmalsburg Avatar asked Dec 02 '22 21:12

tmalsburg


1 Answers

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.

like image 193
Rainer Joswig Avatar answered Feb 12 '23 10:02

Rainer Joswig