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: ~S
how 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-handler
is 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-message
is 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
import
declaration), so anything can happen, depending on the default interpretation of the non-conforming code in the implementation.[Edit] IMHO,
with-exception-handler
should 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,guard
provides a good abstraction.