[plt-scheme] raising / handling errors

From: Danny Yoo (dyoo at hkn.eecs.berkeley.edu)
Date: Mon Feb 27 18:34:08 EST 2006

> I know(?) how to use with-handlers to catch exististing exceptions, and
> in fact, I do this (now) in my read/eval/print loop. But it is not all
> clear (to me) how to go about raising exceptions and handling them. I am
> aware of raise and error, but I'd like to be able to raise an exception
> which will be caught by a handler I install. I recall reading that, say,
> exn:fail:contract:arity corresponds to the predicate
> exn:fail:contract:arity?

Hi Greg,

Here's a small example; let's say that we're writing a function that only
works with numbers and we'd like to raise a you-are-silly exception if we
give that function something else.  (We really should use contracts here,
but let's ignore that for the moment.)

Let's first define a "you-are-silly" kind of exception.  We can do this by
defining an exn:fail:you-are-silly structure:

> (define-struct (exn:fail:you-are-silly exn:fail) ())

We're subtyping on exn:fail to make it a little easier to trap it
generically: we might want to trap things by saying something like:

   (with-handlers ((exn:fail? ...)) ...)

in which case, if we raise an exn:fail:you-are-silly, things are still
going to work ok because exn:fail:you-are-silly is a subtype of exn:fail.

But how do we construct an instance of an exn:fail:you-are-silly
structure?  If we look at Chapter 6 of the reference:


then we can see a description on primitive exceptions in Section 6.1.1.
A main thing to note is that the base 'exn' structure has two fields.
'exn:fail' doesn't introduce any other fields, so that means that our
'exn:fail:you-are-silly constructor' also takes in only two fields:

    * message
    * continuation-marks

We can experimentally see this:

> (procedure-arity make-exn:fail:you-are-silly)

but it's good to know what those two fields mean too.  *grin*

Ok, so let's try this:

> (make-exn:fail:you-are-silly
    "you silly head"

There's our exception object.  Its only a matter now of raising it
whenever we want to castigate the caller.

Let's turn this into a procedure and test this out:

> (define (raise-you-silly)
    (raise (make-exn:fail:you-are-silly
            "you silly head"
> (define (test x)
      [(number? x) (* x x)]
      [else (raise-you-silly)]))
> (test 42)
> (test 'muhahah)
you silly head

I hope this helps!

Posted on the users mailing list.