ELisp: Exit Loop or Function (throw, catch)

By Xah Lee. Date: . Last updated: .

To exit a loop or exit a function:

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

catch
(catch 'tagName body)

Evaluates body and return body's last expression, but if body contains (throw …) and it is called, return the value throw passes.

throw
(throw 'tagName passValue)

Jump to a outer (catch 'tagName) and continue there, passing the value of passValue to it. Both tagName passValue are evaluated.

;; example of exit a while loop
;; prints a random integer between 0 to 10, inclusive
;; if 5 comes up, then exit after printing it
(catch 'abc
  (while (setq xx (random 10))
    (message "%s" xx)
    (when (eq 5 xx) (throw 'abc t))))

Exit a Function

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

;; demo using catch/throw to exit function.

(defun xx-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 'aaa
    (if (> x 5)
        (progn
          (throw 'aaa "yes"))
      (progn
        "no"
        ))))

(string-equal (xx-test-exit 2) "no")
(string-equal (xx-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")
      )))

Exit a Iteration

You can also use throw to exit a map or loop.

💡 TIP: you can also use seq-some. [see ELisp: Sequence Functions]

;; demo using throw catch to exit a mapping
(let ((xseq [0 1 2 3 4 5]))
  ;; map lambda onto a list. If value 3 is found, return 3, else nil
  (catch 'bbb
    (mapc
     (lambda (x)
       (message "%s" x)
       (when (equal x 3) (throw 'bbb x)))
     xseq)
    nil
    ))

Reference

Emacs Lisp Function

Emacs Lisp, Loop and Iteration