(define-condition malformed-log-entry-error (error) ((text :initarg :text :reader text))) ;; this is totally unremarkable. Very similar to how an ;; exception type is defined in Java (defun parse-log-entry (text) (if (well-formed-log-entry-p text) (make-instance 'log-entry ...) (error 'malformed-log-entry-error :text text))) ;; signal an error if malformed. ;; ;; Default behavior--land in the debugger ;; ;; * Providing multiple restarts (defun parse-log-entry (text) (if (well-formed-log-entry-p text) (make-instance 'log-entry ...) (restart-case (error 'malformed-log-entry-error :text text) (use-value (value) value) (reparse-entry (fixed-text) (parse-log-entry fixed-text))))) ;; Here, the error can be handled in two ways-- ;; ;; use-value: have a handler provide a value ;; ;; reparse-entry: have a handler provide a different text to ;; parse (defun log-analyzer () (handler-bind ((malformed-log-entry-error #'(lambda (c) (use-value (make-instance 'malformed-log-entry :text (text c)))))) (dolist (log (find-all-logs)) (analyze-log log))))