[racket] understanding racket exceptions

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Fri Sep 3 15:03:04 EDT 2010

That's my understanding of it too. [Maybe modulo parameters rather
than marks themselves.]

Jay

On Fri, Sep 3, 2010 at 12:05 PM, Danny Yoo <dyoo at cs.wpi.edu> wrote:
> I'm about to try replicating Racket's exception system in WeScheme, so
> I want to make sure I understood the model beforehand.  Here's my
> understanding of the system, and if people can correct me, I'd greatly
> appreciate it!
>
>
> * Exception handlers are managed by keeping a chain of these handlers
> within the continuation marks.  A form like with-handlers effectively
> extends the chain within its dynamic extent.  There's a designated
> continuation-marks key used to keep track of exception handlers.  This
> key is internal and otherwise inaccessible to the outside world.  Let
> me call this key "K" for the moment.  If it were possible to get at K,
> then hypothetically I would be able to observe it by doing something
> like this:
>
>  (begin
>    (printf "Before: ~s~n" (continuation-mark-set->list
> (current-continuation-marks) K))
>    (with-handlers ([exn void])
>       (printf "Within: ~s~n" (continuation-mark-set->list
> (current-continuation-marks) K)))
>
>
> * Whenever an exception happens, the runtime immediately grabs the
> current continuation marks and extracts the chain of exception
> handlers associated to K.  It then walks the chain.  Each element in
> the chain is responsible for returning the exception up the chain.  If
> an exception handler knows what to do with an exception, and wants to
> interrupt the chain, then it is supposed to call the
> error-escape-handler to stop the rest of the computation.
>
>
> I looked at the exceptions proposal [Friedman95
> http://www.cs.indiana.edu/scheme-repository/doc.proposals.exceptions.html
> ].  I see that the proposal defines a current-exception-handlers, but
> I don't see such a function in Racket.  I assume that the only way to
> adjust the current exception handler is through
> call-with-exception-handler.
>
>
>
> If I wanted to simulate the exception-handling mechanism, it might
> look something like this:
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> #lang racket
>
> (define K (cons "my-distinguished"
>                "exception key!"))
>
>
> (define-syntax (simulate stx)
>  (syntax-case stx ()
>    [(_ body ...)
>     (syntax/loc stx
>       (call-with-exception-handler my-exception-handler
>                                    (lambda ()
>                                      body ...)))]))
>
>
> (define (my-uncaught-exception-handler exn)
>  (printf "I am the uncaught exception handler, seeing ~s~n" exn)
>  (abort-current-continuation (default-continuation-prompt-tag) void))
>
>
> (define (my-exception-handler exn)
>  (printf "my-exception-handler\n")
>  (let ([handlers
>         (continuation-mark-set->list (current-continuation-marks)
>                                      K)])
>    (printf "I see the following handlers: ~s\n" handlers)
>    (let ([exn
>           (foldl (lambda (a-handler exn)
>                    (a-handler exn))
>                  exn
>                  handlers)])
>
>      ;; At this point, calls the uncaught-exception-handler if none of the
>      ;; handlers will support us.
>      (printf "Uncaught exception handler kicking in.\n")
>      (my-uncaught-exception-handler exn)
>      (printf "I should never see this!\n"))))
>
>
> (define-syntax (my-with-handlers stx)
>  (syntax-case stx ()
>    [(_ ([exn-test? on-exn]
>         ...)
>        body ...)
>     (syntax/loc stx
>       ;; NOTE: I need to make sure the with-continuation-mark is not
> in tail position,
>       ;; or else my t2 shows that an exception handlers has been
> replaced, rather than nested.
>       (let ([result
>              (with-continuation-mark K (lambda (exn)
>                                          (cond
>                                            [(exn-test? exn)
>                                             (on-exn exn)
>                                             (abort-current-continuation
>                                              (default-continuation-prompt-tag)
>                                              void)]
>                                            ...
>                                            [else
>                                             exn]))
>
>                (begin body ...))])
>         result))]))
>
>
> ;; test1: see that I can catch an exception
> (define (t1)
>  (simulate (my-with-handlers ((exn:fail? (lambda (exn)
>                                            (printf "Oh!  I see ~s~n" exn))))
>                              (printf "Starting up~n")
>                              (/ 1 0))))
>
> ;; test2: see that I can observe the nesting, and also fire off the
> uncaught exception handler
> (define (t2)
>  (simulate (my-with-handlers ()
>                              (printf "Starting up~n")
>                              (my-with-handlers ()
>                                                (/ 1 0)))))
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> _________________________________________________
>  For list-related administrative tasks:
>  http://lists.racket-lang.org/listinfo/users
>



-- 
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://teammccarthy.org/jay

"The glory of God is Intelligence" - D&C 93


Posted on the users mailing list.