I apologize for my last post, which was rather unstructured.
I have tracked down a very simple piece of code that illustrates the
problem:
>>>=================
(guard (ball
(#f (display "Caught exception."))) ; <-- Clause 1
(guard (ball
(#f (raise ball))) ; <-- Clause 2
(raise 'exn)))
<<<=================
The code above uses the reference implementation of SRFI34 (I only added
a (display "reraise") so that I can se when an exception is reraised due
to no matching guard clause).
As it stands, the evaluation goes into a reraise loop. The loop can be
broken by chaning the "#f" to "else" in either of the marked clauses.
By chaning in Clause 1 I get the output "Cauhgt exception.". By
changing Clause 2 I get the output "Unhandled exception: exn".
Why don't I get "Unhandled exception: exn" right away?
Thanks,
Henrik Tidefelt
Because the reference implementation doesn't implement GUARD
properly. The description of GUARD says:
If every <clause>'s <test> evaluates to false and there is
no else clause, then raise is re-invoked on the raised object
within the dynamic environment of the original call to raise
*except that the current exception handler is that of the guard
expression*.
The GUARD implementation doesn't do the *'ed part at the end.
Sorry about that. I'll append a quick fix which works for your
example, at least.
-Richard Kelsey
(define (raise obj)
(really-raise obj *current-exception-context*))
(define (really-raise obj context)
(with-dynamic-environment
(exception-context-dynamic-env context)
(lambda ()
(with-exception-handler (lambda (exp)
((exception-context-previous-handler context)
exp))
(lambda ()
((exception-context-handler context) obj)
(error "handler returned"
(exception-context-handler context)
obj))))))
(define-syntax guard
(syntax-rules ()
((guard (var clause ...) e1 e2 ...)
((call-with-current-continuation
(lambda (k)
(let ((context *current-exception-context*))
(with-exception-handler
(lambda (var)
(let ((env (current-dynamic-environment)))
(k
(lambda ()
(let ((condition var))
(guard-aux (with-dynamic-environment env
(lambda ()
(really-raise
condition
context)))
clause ...))))))
(lambda ()
(call-with-values
(lambda () e1 e2 ...)
(lambda args
(k (lambda ()
(apply values args))))))))))))))