The exception system in
MzScheme is the one proposed by
Friedman, Haynes and Dybvig.
A program can signal an exceptional situation by
raising an expression. The form
(raise exn) will pass
exn, which can be anything, to the
current exception handler. The form
with-handlers can be used to temporarily extend the current exception handler while executing its body of code.
> (define (always-true exn) #t)
> (define (my-handler exn)
(for-each display
(list "Exception caught: " exn "\n")))
> (with-handlers ([always-true my-handler])
(/ 1 0))
Exception caught: #<struct:exn:application:divide-by-zero>
The above example used the predicate
always-true to determine whether the exception handler
my-handler should take care of the exception or whether it should be passed on to the current exception handler. Since
always-true always returns
#t all exceptions will be handled by
my-handler.
Since the stop button in
DrScheme works by raising a break exception, normally one uses the predicate
exn:fail? in order to catch all
exceptions but breaks. If
exn:fail? is used, the stop button works even if a programming mistake is made in the exception handler.
> (with-handlers ([exn:fail? (let loop () (loop))])
(/ 1 0))
[bug icon] user break
>
It is good style to only catch the exceptions that one is interested in. Therefore check the
HelpDesk to see, what exceptions are thrown by the various functions.
As an example lets look at
tcp-connect. The
HelpDesk says:
If a connection cannot be established by tcp-connect, the exn:fail:network exception is raised.
Therefore we need to catch the
exn:fail:network exception:
> (with-handlers ([exn:fail:network? my-handler])
(tcp-connect "www.scheme.dk" 83))
Exception caught: #<struct:exn:fail:network>
Notice that
tcp-connect blocks breaks. If you want to enable breaks during tcp-connects use the function
tcp-connect/enable-break instead.
--
JensAxelSoegaard - 26 Apr 2004
The following snippet shows how we can create application-level exceptions that subtype
exn:fail.
(define-struct (exn:fail:you-silly-head exn:fail) ())
(define (raise-you-silly-head)
(raise (make-exn:fail:you-silly-head
"you silly head"
(current-continuation-marks))))
If you want to raise an exception in response to a lower-level exception, and both are subtypes of
exn, set the continuation-marks field of the new exception using those from the lower-level exception. This allows a stack trace to show the source of the original exception. For example:
(with-handlers ((exn:fail? (lambda (e)
(raise (make-exn:fail:you-silly-head
(exn-message e)
(exn-continuation-marks e))))))
...)
not-break-exn? is obsolete as of one of the PLT v299 revisions. I believe it has been replaced by
exn:fail?.
--
AntonVanStraaten - 11 Oct 2005