Elisp Loop and Iteration

Table of Contents

1. Loops

1.1. While Loop

  (while test body)

where body is one or more lisp expressions. Usually, it’s used along with let to set up index variables.

1.2. Loop for a Fixed Number of Times

We can use dotimes to loop for a fixed number of times. It has two formats.

  (dotimes (VAR COUNT) BODY)
  (dotimes (VAR COUNT RESULT) BODY)

Basically, it evaluate BODY with VAR bound to successive integers (starting from 0 to COUNT - 1). When the loop ends, it returns nil (first variant) or the evaluated RESULT expression (second variant).

BODY can be one or more expressions.

  ;; e.g.
  (dotimes (i 4)
    (insert (number-to-string i))) ; inserts 0123

2. Iteration over List

We use dolist to iterate over list.

  (dolist (VAR LIST) BODY)
  (dolist (VAR LIST RESULT) BODY)

Each time evaluate BODY, with VAR having value of an element in list. Returns nil (first variant) or the evaluated RESULT expression (second variant).

3. Exit Loops or Functions

There’s no break, continue or return keywords in Emacs Lisp. So we have other ways to achieve the same effect.

3.1. Throw and Catch

  (catch tag body)

  (throw tag passValue)

Evaluates body and returns body’s last expression, but if body contains throw with same tag and the throw is called, it exits the entire catch and return the value throw passes.

tag effectively must be an integer or symbol, because throw matches tag by eq function.

  ;; e.g. exit a loop
  (catch 1111
    (while (setq xx (random 10))
      (print xx)
      (when (eq 5 xx) (throw 1111 t)))) ; if 5 comes up, exit

  ;; e.g. exit a function
  (defun my-test-exit (x)
    "If x is greater than 5, return string yes, else return no."
    (catch 11
      (if (> x 5)
          (progn
            (throw 11 "yes"))
        (progn "no"))))

3.2. Use seq-some or seq-every-p

3.3. Use error or user-error to Signal Error and Exit Process

Date: 2026-07-21 Tue