[This is something to be discussed during a future revision of Scheme,
but I want to make a note of it while I'm thinking of it, and I think
others using R6RS may want to know about the issue.]
R6RS's continuable exceptions do not seem to work well with reraising.
I think exception handlers should be able to reraise any exception
transparently. So, I've been reraising using `raise-continuable' in
case whatever outer handler which does handle the exception wants to
return to the original raise. If the original raise was done with
`raise', not `raise-continuable', then a `&non-continuable' exception is
raised with the current exception handler being the one that was in
place when the handler which returned to the `raise' was installed. The
current design does not allow you to handle such possible
`&non-continuable' exceptions as I think should be done (you could make
your own implementation like I show below, but it won't be standard and
so won't work with other people's libraries who don't use it), because
the innermost handler, which reraised using `raise-continuable', ends up
being the one that returns to a `raise' and so the next innermost
handler gets the `&non-continuable'; however, it should be the handler
of the outermost handler which decided to return that gets the
`&non-continuable'.
For example:
;;;;;;;;;;;;;;; reraising-problem.sps ;;;;;;;;;;;;;;;
#!r6rs
(import (rnrs (6)))
(with-exception-handler
(lambda (ex)
(display "E.H. 1\n")
(display "Unhandled Exception:\n")
(write (simple-conditions ex)) (newline)
(exit #F))
(lambda ()
(with-exception-handler
(lambda (ex)
(display "E.H. 2\n")
(if (warning? ex)
'return-value
(raise-continuable ex)))
(lambda ()
(with-exception-handler
(lambda (ex)
(display "E.H. 3\n")
(raise-continuable ex))
(lambda ()
(with-exception-handler
(lambda (ex)
(display "E.H. 4\n")
(raise-continuable ex))
(lambda ()
(raise-continuable (make-warning))
#;(raise (make-warning))
(display "Continued.\n")))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$ ikarus --r6rs-script reraising-problem.sps
E.H. 4
E.H. 3
E.H. 2
Continued.
$
Now, if we comment-out the `(raise-continuable (make-warning))' and
uncomment the `(raise (make-warning))':
$ ikarus --r6rs-script reraising-problem.sps
E.H. 4
E.H. 3
E.H. 2
E.H. 3
E.H. 2
E.H. 1
Unhandled Exception:
(#[&non-continuable] #[&message "handler returned"])
$
Which shows the `&non-continuable' was first given to E.H. 3. But I
think the right thing is for E.H. 1 to get the `&non-continuable'
because it's the handler for the handler which improperly returned and
inner handlers should not have to deal with the problems of outer
handlers.
To accomplish this, I'm thinking the exceptions design needs to be
changed so exceptions are discernable as continuable or non-continuable.
This would allow making a `reraise' procedure which reraises using
`raise' or `raise-continuable' depending on whether the exception to be
reraised is non-continuable or continuable. This would allow handlers
to reraise so that an outer handler can return to an original
`raise-continuable', but if it returns when the original was a `raise',
it returns to the `raise' in the outermost `reraise' and so its handler
gets the `&non-continuable' as it should. Also, I imagine being able to
discern exceptions as continuable or not might be useful in other ways.
A new `&continuable' condition type could be added which is present in
continuable exceptions (i.e., added to whatever is raised via
`raise-continuable') and not present in non-continuable exceptions
(those raised via `raise'). This would require also changing the design
so all exceptions are conditions so they can possibly have a
`&continuable' added and so they can be tested if they have a
`&continuable'. Raising arbitrary non-condition objects is still
possible by putting them in a field of a condition record. Also, I'm
thinking `raise' should remove any possible `&continuable' components.
The below example `(reraise)' library does all this.
I think I'm going to make all my code use a `reraise' procedure, which
for now will just do `raise-continuable', in hopes I can change it in
the future to a `reraise' like I'm describing which will use standard
facilities and so work with other's libraries.
Changing `reraising-problem.sps' to instead use the below library:
@@ -1,5 +1,7 @@
#!r6rs
-(import (rnrs (6)))
+(import
+ (except (rnrs (6)) raise raise-continuable)
+ (reraise))
(with-exception-handler
(lambda (ex)
(display "E.H. 1\n")
@@ -12,17 +14,17 @@
(display "E.H. 2\n")
(if (warning? ex)
'return-value
- (raise-continuable ex)))
+ (reraise ex)))
(lambda ()
(with-exception-handler
(lambda (ex)
(display "E.H. 3\n")
- (raise-continuable ex))
+ (reraise ex))
(lambda ()
(with-exception-handler
(lambda (ex)
(display "E.H. 4\n")
- (raise-continuable ex))
+ (reraise ex))
(lambda ()
#;(raise-continuable (make-warning))
(raise (make-warning))
It does:
$ ikarus --r6rs-script reraising-problem.sps
E.H. 4
E.H. 3
E.H. 2
E.H. 1
Unhandled Exception:
(#[&non-continuable] #[&message "handler returned"])
$
Which shows E.H. 1 was given the `&non-continuable' that was raised when
E.H. 2 improperly returned.
;;;;;;;;;;;;;;; reraise.sls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#!r6rs
(library (reraise)
(export
&continuable make-continuable-condition continuable-condition?
raise raise-continuable reraise)
(import
(except (rnrs (6)) raise raise-continuable)
(prefix (only (rnrs (6)) raise raise-continuable) r6rs:))
(define-condition-type &continuable &condition
make-continuable-condition continuable-condition?)
(define (raise ex)
(assert (condition? ex))
(r6rs:raise
(if (continuable-condition? ex)
(apply condition
(remp continuable-condition?
(simple-conditions ex)))
ex)))
(define (raise-continuable ex)
(assert (condition? ex))
(r6rs:raise-continuable
(if (continuable-condition? ex)
ex
(condition (make-continuable-condition) ex))))
(define (reraise ex)
(assert (condition? ex))
(if (continuable-condition? ex)
(r6rs:raise-continuable ex)
(r6rs:raise ex)))
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
--
: Derick
----------------------------------------------------------------
_______________________________________________
r6rs-discuss mailing list
[email protected]
http://lists.r6rs.org/cgi-bin/mailman/listinfo/r6rs-discuss