## The loop macro in emacs lisp

| categories: emacs_lisp | tags: | View Comments

I was reading The Land Of Lisp chapter on the loop macro in Common Lisp. I am not too familiar with it, or the implementation in emacs-lisp, so in this post we explore what it can do. Here I will explore some uses of the loop macro to do things I used to do in Python all the time.

Here is a simple example to generate a list of numbers with the loop macro..

(loop for i
below 5
collect i)

 0 1 2 3 4

Evidently, i starts at 0, and increments by one. We can specify a different value like this. Here we use the to token, which also includes the last value.

(loop for i from 2 to 10
collect i)

 2 3 4 5 6 7 8 9 10

IF you want to go backwards:

(loop for i downfrom 10 to 2 collect i)

 10 9 8 7 6 5 4 3 2

And if you want an (de)increment different than one, use the by token.

(loop for i downfrom 10 to 2 by 3 collect i)

 10 7 4

We can use this to iterate over a list too. Let us collect the square of each element in a simple list. This is similar to the mapcar function.

(loop for i in '(1 2 3 4)
collect (* i i))

 1 4 9 16

You can combine the ideas to get something similar to the enumerate function in python.

(loop for i
from 0
for month
in '(january february march april may june july august september
october november december)
collect (cons i month))

((0 . january)
(1 . february)
(2 . march)
(3 . april)
(4 . may)
(5 . june)
(6 . july)
(7 . august)
(8 . september)
(9 . october)
(10 . november)
(11 . december))


The loop stops because we run out of months to iterate over. Here is a variation like the zip function in python.

(loop for element1 in '(a b c d)
for element2 in '(1 2 3 4)
collect (list element1 element2))

 a 1 b 2 c 3 d 4

We can sum in the loop:

(loop for i in '(100 200 300) sum i)

600


We can conditionally sum things in the loop, e.g. sum only the odd numbers.

(loop for i in '(1 2 3 4 5)
when (oddp i)
sum i)

9


We can find the minima and maxima in a list

(loop for i in '(-1 0 1)
minimize i)

-1

(loop for i in '(-1 0 1)
maximize i)

1


You may want to do some action in the loop. Say we want to print even numbers from a list.

(loop for i in '(1 2 3 4)
when (evenp i)
do (print i))

2

4


There are some ways to break out of a loop using return like this.

(loop for i upto 10
when (= i 3)
return 'done
do (print i))

0

1

2


Alternatively, you can use while/until.

(loop for i downfrom 10
do (print i)
until (= i 6))

10

9

8

7

6


Or the while variation:

(loop for i downfrom 10
do (print i)
while (> i 6))

10

9

8

7

6


## 1 Summary

This is not everything the loop macro can do! Here is what the help for that function says.

loop is an alias for cl-loop' in cl.el'.

(loop CLAUSE...)

The Common Lisp loop' macro.
Valid clauses include:
For clauses:
for VAR from/upfrom/downfrom EXPR1 to/upto/downto/above/below EXPR2 by EXPR3
for VAR = EXPR1 then EXPR2
for VAR in/on/in-ref LIST by FUNC
for VAR across/across-ref ARRAY
for VAR being:
the elements of/of-ref SEQUENCE [using (index VAR2)]
the symbols [of OBARRAY]
the hash-keys/hash-values of HASH-TABLE [using (hash-values/hash-keys V2)]
the key-codes/key-bindings/key-seqs of KEYMAP [using (key-bindings VAR2)]
the overlays/intervals [of BUFFER] [from POS1] [to POS2]
the frames/buffers
the windows [of FRAME]
Iteration clauses:
repeat INTEGER
while/until/always/never/thereis CONDITION
Accumulation clauses:
collect/append/nconc/concat/vconcat/count/sum/maximize/minimize FORM
[into VAR]
Miscellaneous clauses:
with VAR = INIT
if/when/unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...]
named NAME
initially/finally [do] EXPRS...
do EXPRS...
[finally] return EXPR

For more details, see Info node (cl)Loop Facility'.


It is obviously quite powerful, although the syntax seems quite different than the usual lisp code I have been writing. It is not clear when this is superior to something like mapcar/mapconcat, or the dolist/dotimes functions.