[racket] understanding racket exceptions
It looks like you have `call-with-exception-handler' right, but not
`with-handlers'.
The exception handler installed by `with-handlers' needs to escape to
the context of the `with-handlers' form before finding whether any
handlers apply. In other words, `with-handlers' combines a prompt
(using a generated tag) with a continuation mark. If no handler is
found, the exception should be re-raised using `raise'.
At Fri, 3 Sep 2010 14:05:43 -0400, Danny Yoo 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