Non-Local Exits

;; block / return-from: lexical exit
(defun find-negative (list)
  (dolist (x list)                        ; dolist establishes an implicit block named NIL
    (when (minusp x) (return x))))
(find-negative '(1 2 -3 4))               ; -3

(defun search-grid (grid target)
  (block search
    (dotimes (i (array-dimension grid 0))
      (dotimes (j (array-dimension grid 1))
        (when (eql (aref grid i j) target)
          (return-from search (list i j)))))
    nil))
;; Every defun establishes a block named after the function: (return-from my-function value)

;; catch / throw: dynamic exit (the tag is looked up at runtime)
(defun deep-search (x) (when (= x 42) (throw 'found x)) nil)
(catch 'found
  (dolist (x '(1 42 3)) (deep-search x))
  :not-found)                             ; 42

;; unwind-protect: cleanup that always runs
(defun with-resource-demo ()
  (let ((resource (acquire-resource)))
    (unwind-protect
         (use-resource resource)          ; protected form
      (release-resource resource))))      ; cleanup forms run on normal exit AND on non-local exits/errors

;; tagbody / go: low-level goto (used inside macros like loop and prog)
(let ((i 0))
  (tagbody
   top
   
…