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.

catch
(catch tagSymbol body)

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

tagSymbol is a Symbol.

throw
(throw tagSymbol passValue)

Jump to a outer catch of the same tagSymbol and continue there, passing the value of passValue to it. Both tagSymbol passValue are evaluated.

;; example of exit a while loop
;; prints a random integer
;; if 5 comes up, exit
(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 or Loop

You can also use throw to exit a loop.

💡 TIP: you can also use seq-some. 〔see Elisp: Sequence Iteration, Conditional Exit

;; 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

Elisp, Function

Elisp, Loop and Iteration