Exceptions and Error Handling

28.1 Raising

(error "Something failed:" 42 'details)      ; raises an error object (message + irritants)
(raise 'my-symbol)                           ; raise ANY object (non-continuable)
(raise-continuable 'warning)                 ; the handler's return value becomes raise-continuable's value
(assert (> 1 0))                             ; R6RS/implementations (not in R7RS-small)

28.2 guard (Catch and Recover)

(define (safe-div a b)
  (guard (e ((error-object? e)
             (display "Error: ")
             (display (error-object-message e))
             (display (error-object-irritants e))
             (newline)
             #f)
            ((symbol? e) (list 'symbol-raised e))
            ((string? e) (string-append "caught: " e)))
    (if (= b 0)
        (error "division by zero" a)
        (/ a b))))

(safe-div 10 2)                              ; 5
(safe-div 10 0)                              ; prints "Error: division by zero(10)", returns #f

(guard (e (#t (list 'caught e)))             ; catch everything
  (raise 'boom))                             ; (caught boom)

(guard (e ((string? e) 'string))             ; no clause matches → re-raised to the outer handler
  (raise 42))

;; => in guard clauses
(guard (e ((assq 'code (if (list? e) e '())) => cdr))
  (raise '((code . 404) (msg . "not found"))))   ; 404

28.3 with-exception-handler (Low Level)

;; The handler runs in the dynamic context of RAISE (the stack isn't unwound yet)
(with-exception-handler
  (lambda (e) (display "handling ") 10)      ; for raise-continuable, its value is returned
  (lambda () (+ 1 (raise-continuable 'oops))))   ; prints "handling ", returns 11

;; For a non-continuable RAISE, the handler must not return normally: escape with a continuation
(call/cc
  (lambda (k)
    (with-exception-handler
      (lambda (e) (k (list 'recovered e)))
      (lambda () (raise 'fatal)))))          ; (recovered fatal)

28.4 Error Object Predicates (R7RS)

Is it an object created by error?

error-object-message, error-object-irritants Raised by read Raised by file operations

R6RS has a richer condition hierarchy (&error, &assertion, &message, &irritants, condition-message) and (guard ...) with condition predicates.

28.5 Error Handling Styles

Return #f or a sentinel for expected failures (assoc, string->number).

Return tagged results (ok . value) / (err . reason) for richer information.

Raise exceptions for exceptional situations, and catch them at boundaries with guard.