我试图创建计算表达式并将错误作为字符串返回错误的代码:
(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)我有
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)
Unbound variable: ~S如何获得实际错误消息而不是模板?
注意:这是REPL的一部分,我正在系统上的所有Scheme实现中进行测试。它几乎可以工作,它可以自己运行,但是我想在异常发生时显示正确的错误消息,而不是退出REPL。
发布于 2021-01-11 23:34:20
Gauche堆芯
糟了。当然,这并不理想,但可以解释。
默认情况下,由于历史原因,
with-exception-handler是SRFI-18,而不是R7RS。这意味着异常处理程序是在异常发生的动态环境中调用的,包括异常处理程序设置。如果异常处理程序中发生异常,则调用相同的异常处理程序,从而导致无限递归。显然,Gauche的运行时耗尽了C堆栈,或者something.error-object-message没有在Gauche的默认名称空间中定义。因此,这首先触发了一个异常。添加
(import (scheme base) (scheme write) (scheme r5rs))在代码的开头,使程序在R7RS绑定中运行。然后你会得到:
unbound variable: xxx 实际上,您的代码不是一个有效的R7RS程序(至少应该以一个import声明开始),因此任何事情都可能发生,这取决于实现中对不符合的代码的默认解释。
编辑IMHO,with-exception-handler应该被认为是构建易于使用的实用程序的最低层结构,因此应该格外小心地使用。在一般用例中,guard提供了一个很好的抽象。
发布于 2021-01-12 16:24:32
使用Gambit获得无限循环的原因是变量xxx未绑定,因此使用unbound-global-exception对象调用异常处理程序(lambda (e) (exit (error-object-message e))),这将导致调用error-object-message,但参数不是error-object (特定于调用error过程引发的异常),因此引发一个type-exception对象,该type-exception对象将导致调用相同的异常处理程序,以此类推。
如果您想要一个“弹出”当前异常处理程序的异常处理程序,请使用with-exception-catcher而不是with-exception-handler。这将避免无限循环。
可以用Gambit以这种方式将异常对象转换为字符串:
(define (exception->string exc)
(with-output-to-string
(lambda ()
(display-exception exc))))它适用于error-objects和其他类型的异常,以及任何非异常对象.
这是一个更便携的解决方案(表面测试):
(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)发布于 2021-01-14 08:49:21
对Kawa来说:
(define (exception->string exc)
(call-with-port (open-output-string)
(lambda (port)
(display exc port)
(get-output-string port)))))这将将异常转换为字符串并获得错误消息。
https://stackoverflow.com/questions/65667115
复制相似问题