Elisp: Exit Loop or Function (throw, catch)

By Xah Lee. Date: . Last updated: .

Ways to Exit a Loop or Function

🟢 TIP: there is no break, exit, return keywords in emacs lisp.

Throw and Catch

catch

(catch tag body)

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

tag effectively must be a integer or Symbol. Because throw matches tag by eq. 〔see Elisp: Equality Test

🟢 TIP: i recommend using integer for the catch tag. E.g. 1, 2, etc. Because if you use symbol, it pollutes the symbol table. Emacs lisp convention uses symbol.

throw

(throw tag passValue)

Jump to a outer catch of the same tag and continue there, passing the value of passValue to it.

Both tag and passValue are evaluated.

;; example of exit a while loop
;; prints a random integer
;; if 5 comes up, exit
(catch 1111
  (while (setq xx (random 10))
    (print xx)
    (when (eq 5 xx) (throw 1111 t))))

;; same example, but using symbol for tag
(catch 'here
  (while (setq xx (random 10))
    (print xx)
    (when (eq 5 xx) (throw 'here t))))

Example. Exit a Iteration or Loop

;; example of exit a mapc loop
;; if 5 is in it, return "found", else nil
(let ((xlist (list 1 2 3 4 5 6 7 8)))
  (catch 1111
    (mapc
     (lambda (x)
       (if (eq x 5)
           (throw 1111 "found")
         (print x)))
     xlist)
    nil))
;; "found"

Example. Exit a Function

Here is a example using throw to exit a function. Effectively like a return statement in other langs.

;; demo using catch/throw to exit function.

(defun my-test-exit (x)
  "if x is greater than 5, return string yes, else return no"
  ;; here, throw is similar to the return in other langs
  (catch 11
    (if (> x 5)
        (progn
          (throw 11 "yes"))
      (progn
        "no"))))

(my-test-exit 2)
;; "no"

(my-test-exit 6)
;; "yes"

Exit by Error

Exit by calling error or user-error .

(defun test-exit-f ()
  "example"
  (interactive)
  (if (y-or-n-p "invoke user-error to exit?")
      (user-error "Error, because: %s" "you said so!")
    (progn ; else, go on
      (message "went on")
      )))

Reference

Elisp, Function

Elisp, Loop and Iteration