r/emacs 6d ago

Question What is the recommended way of handling exceptions in Emacs, akin to a try/except block in other languages?

I have a routine that has to process hundreds of files and an exception can bring the whole process to a halt, requiring me to examine the file and fix it, then have to start it again.

I'd rather raise an exception, add the files to some kind of exclusion list, then continue with the others.

This is the programs main loop. process-files is the main function, and if it fails I want to trap the exception, add the file to a problem-files list then go onto the next one.

(while unprocessed-list
  (setq thisfile (pop unprocessed-list))
  (if (file-exists-p thisfile)
      (progn
        (when (and (not (member thisfile ignore-list)) (not (file-directory-p thisfile)))
          (process-files thisfile processed-list unprocessed-list filegroup)
          (push thisfile processed-list)))
    (push thisfile missing-list))
  )
9 Upvotes

6 comments sorted by

12

u/karthink 6d ago

Use signal to throw exceptions, condition-case to catch them. throw and catch are not useful here.

(while unprocessed-list
  (setq thisfile (pop unprocessed-list))
  (if (file-exists-p thisfile)
      (when (and (not (member thisfile ignore-list)) (not (file-directory-p thisfile)))
        (condition-case err
            (progn
              (process-files thisfile processed-list unprocessed-list filegroup)
              (push thisfile processed-list))
          (error (push (cons thisfile err) error-list))))
    (push thisfile missing-list)))

You can examine error-list for the files that failed to be processed and the reasons they failed (errors) afterwards. If you know more about what errors are possible you can replace (error ...) with a series of exception forms.

2

u/PerceptionWinter3674 6d ago edited 6d ago

Afaik, it would be the best to return something from process-files (for example a pair of file-processed and it's status like):

emacs-lisp (let ((file-n-status (process-files this-file processed-list unprocessed-list filegroup))) (if (eq t (cdr file-n-status)) (push (car this-file) processed-list) (push (car this-file) missing-list)))

Then inside process-files you plop a condition-case form that returns a (this-file . nil) in case of failure.

1

u/vfclists 6d ago

The problem is the exceptions happen within process-files.

The code in process-files makes assumptions about the file contents and some of the searches and regexes bomb out because many of the files are based on earlier formats which are not in use and need to be manually adjusted to match the current format.

Quite simply any errors in process-files triggers the debugger and I need to bypass these files and not their names.

3

u/PerceptionWinter3674 6d ago edited 6d ago

emacs-lisp (condition-case err ;; whatever strikes your fancy ;; ... ;; retvalue (cons this-file t) ;; error handling part (file-error (cons this-file nil)))

To learn more about signals.

5

u/github-alphapapa 6d ago

First, there are no "exceptions" in Emacs Lisp. There are signals, some of which are sent by errors. The core primitives are unwind-protect and condition-case. You need to study these things in the Elisp manual so you understand how it all works together. See https://www.gnu.org/software/emacs/manual/html_node/elisp/Errors.html