Custom Errors in Lisp

(defpackage :custom-errors
  (:use :cl))

(in-package :custom-errors)

;; A custom error type usually has the suffix "Error".
(defstruct arg-error
  arg
  message)

;; Adding this error-message method makes arg-error behave like an error.
(defmethod error-message ((e arg-error))
  (format nil "~A - ~A" (arg-error-arg e) (arg-error-message e)))

(defun f (arg)
  (if (= arg 42)
      ;; Return our custom error.
      (values -1 (make-arg-error :arg arg :message "can't work with it"))
      (values (+ arg 3) nil)))

(defun main ()
  ;; In Common Lisp, we don't have a direct equivalent to errors.As,
  ;; but we can check the type of the error and extract information from it.
  (multiple-value-bind (result err) (f 42)
    (declare (ignore result))
    (if (typep err 'arg-error)
        (progn
          (format t "~A~%" (arg-error-arg err))
          (format t "~A~%" (arg-error-message err)))
        (format t "err doesn't match arg-error~%"))))

(main)

This code demonstrates how to create and use custom error types in Common Lisp. Here’s a breakdown of the translation:

  1. We define a package custom-errors to encapsulate our code.

  2. We create a custom error type arg-error using defstruct. This is similar to defining a custom struct in other languages.

  3. We define an error-message method for our arg-error type. This is analogous to implementing the Error() method in other languages.

  4. The f function is translated directly. It returns multiple values in Lisp, which is similar to returning multiple values in other languages.

  5. In the main function, we use multiple-value-bind to capture both return values from f.

  6. Instead of errors.As, we use typep to check if the error is of type arg-error. If it is, we print its contents.

To run this program, you would typically save it to a file (e.g., custom-errors.lisp) and then load and run it in a Common Lisp REPL:

$ sbcl --load custom-errors.lisp
42
can't work with it

This example shows how Common Lisp handles custom error types and multiple return values, which are concepts similar to those in the original code.