I'm trying to create code that evaluates expression and return error as string for error:
(cond-expand
(gambit)
(gauche)
(kawa)
(guile
(import (rnrs base)
(rnrs exceptions)
(rnrs conditions))
(define (error-object-message cond)
(condition-message cond))))
(define (evaluate expr env)
(call-with-current-continuation
(lambda (exit)
(with-exception-handler
(lambda (e)
(exit (error-object-message e)))
(lambda ()
(eval expr env))))))
;; trigger error
(display (evaluate 'xxx (interaction-environment)))
(newline)
I've got
- Guile message
Unbound variable: ~Show to get actual error message and not a template? - Kawa exception:
Argument #1 'unbound location: xxx' to 'error-object-message' has wrong type (gnu.mapping.UnboundLocationException) (gnu.mapping.UnboundLocationException cannot be cast to kawa.lang.NamedException) - Gauche core dump
- Gambit freezes
NOTE: this is part of REPL that I'm testing in all Scheme implementations that I have on my system. It almost work, it can run itself, but I would like to show proper error message when exception happen, instead of exiting the REPL.
Oops. It's not ideal, for sure, but it can be explained.
with-exception-handleris SRFI-18's, not R7RS's, because of a historical reason. That means the exception handler is called in the dynamic environment where the exception occurs, including exception handler settings. If an exception occurs within the exception handler, the same exception handler is invoked, causing unbounded recursion. Apparently Gauche's runtime eats up C stack or something.error-object-messageis not defined in Gauche's default namespace. So that triggers an exception in the first place.Add
at the beginning of code makes the program run in R7RS bindings. Then you'll get:
Actually, your code is not a valid R7RS program (which should begin with at least one
importdeclaration), so anything can happen, depending on the default interpretation of the non-conforming code in the implementation.[Edit] IMHO,
with-exception-handlershould be considered as the lowest level construct on which easy-to-use utilities are built, and thus should be used with extra care. In general use case,guardprovides a good abstraction.