The reason you get an infinite loop with Gambit is that the variable xxx
is unbound so the exception handler (lambda (e) (exit (error-object-message e)))
is called with an unbound-global-exception
object and this causes error-object-message
to be called but the parameter is not an error-object
(which is specific to the exceptions raised by a call to the error
procedure) so this raises a type-exception
object that causes the same exception handler to be called, and so on forever.
If you want an exception handling that "pops" the current exception handler, use with-exception-catcher
instead of with-exception-handler
. This will avoid the infinite loop.
Converting an exception object to a string can be done in Gambit this way:
(define (exception->string exc)
(with-output-to-string
(lambda ()
(display-exception exc))))
It works for error-objects
and other kinds of exceptions, and also any non-exception object.
This is a more portable solution (superficially tested):
(import (scheme base)
(scheme r5rs))
(cond-expand
((or lips kawa gauche)
(define (exception->string exc)
(error-object-message exc)))
(gambit
(define (exception->string exc)
(with-output-to-string
(lambda ()
(display-exception exc)))))
(guile
(import (rnrs base)
(rnrs exceptions)
(rnrs conditions))
(define (exception->string exc)
(condition-message exc))))
(define (evaluate expr env)
(call-with-current-continuation
(lambda (exit)
(with-exception-handler
(lambda (e)
(exit (exception->string e)))
(lambda ()
(eval expr env))))))
(display (evaluate 'xxx (interaction-environment)))
(newline)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…