Scheme 如何在方案中显示来自eval的错误消息?

Scheme 如何在方案中显示来自eval的错误消息?,scheme,guile,gambit,kawa,Scheme,Guile,Gambit,Kawa,我正在尝试创建对表达式求值并以字符串形式返回错误的代码: (cond展开) (开局) (笨拙) (川) (诡计 (导入(rnrs基) (rnrs例外) (rnrs条件) (定义(错误对象消息条件) (条件消息cond))) (定义(评估expr env) (使用当前延续调用) (兰姆达(出口) (带异常处理程序) (λ(e) (退出(错误对象消息e))) (lambda() (评估专家环境(()()))) ;; 触发错误 (显示(评估“xxx(交互环境))) (新行) 我有 Guile me

我正在尝试创建对表达式求值并以字符串形式返回错误的代码:

(cond展开)
(开局)
(笨拙)
(川)
(诡计
(导入(rnrs基)
(rnrs例外)
(rnrs条件)
(定义(错误对象消息条件)
(条件消息cond)))
(定义(评估expr env)
(使用当前延续调用)
(兰姆达(出口)
(带异常处理程序)
(λ(e)
(退出(错误对象消息e)))
(lambda()
(评估专家环境(()())))
;; 触发错误
(显示(评估“xxx(交互环境)))
(新行)
我有

  • Guile message
    未绑定变量:~S
    如何获取实际错误消息而不是模板
  • Kawa异常:
    参数#1“unbound location:xxx”到“error object message”的类型错误(gnu.mapping.UnboundLocationException)(gnu.mapping.UnboundLocationException不能强制转换为Kawa.lang.NamedException)
  • 粗芯堆
  • 开局冻结
注意:这是REPL的一部分,我正在系统上所有Scheme实现中测试它。它几乎可以工作,它可以自己运行,但我想在异常发生时显示正确的错误消息,而不是退出REPL

粗芯堆

哎呀。当然,这并不理想,但可以解释

  • 默认情况下,由于历史原因,Gauche的带异常处理程序的
    是SRFI-18,而不是R7RS。这意味着在发生异常的动态环境中调用异常处理程序,包括异常处理程序设置。如果异常处理程序中发生异常,将调用相同的异常处理程序,从而导致无限递归。显然,Gauche的运行时耗尽了C堆栈之类的东西
  • 错误对象消息
    未在Gauche的默认命名空间中定义。因此,这首先会触发一个异常

在代码开始时,使程序在R7RS绑定中运行。然后你会得到:

unbound variable: xxx 
实际上,您的代码不是有效的R7RS程序(它应该至少以一个
import
声明开始),因此任何事情都可能发生,这取决于实现中对不一致代码的默认解释

[编辑]IMHO,
和异常处理程序
应被视为构建易于使用的实用程序的最低级别构造,因此应格外小心地使用。在一般用例中,
guard
提供了良好的抽象

粗芯堆

哎呀。当然,这并不理想,但可以解释

  • 默认情况下,由于历史原因,Gauche的带异常处理程序的
    是SRFI-18,而不是R7RS。这意味着在发生异常的动态环境中调用异常处理程序,包括异常处理程序设置。如果异常处理程序中发生异常,将调用相同的异常处理程序,从而导致无限递归。显然,Gauche的运行时耗尽了C堆栈之类的东西
  • 错误对象消息
    未在Gauche的默认命名空间中定义。因此,这首先会触发一个异常

在代码开始时,使程序在R7RS绑定中运行。然后你会得到:

unbound variable: xxx 
实际上,您的代码不是有效的R7RS程序(它应该至少以一个
import
声明开始),因此任何事情都可能发生,这取决于实现中对不一致代码的默认解释


[编辑]IMHO,
和异常处理程序
应被视为构建易于使用的实用程序的最低级别构造,因此应格外小心地使用。在一般用例中,
guard
提供了一个很好的抽象。

使用Gambit获得无限循环的原因是变量
xxx
未绑定,因此异常处理程序
(lambda(e)(退出(错误对象消息e)))使用
未绑定全局异常
对象调用
,这会导致调用
错误对象消息
,但参数不是
错误对象
(该参数特定于调用
错误
过程引发的异常)因此,这会引发一个
类型异常
对象,导致调用相同的异常处理程序,以此类推

如果希望异常处理“弹出”当前异常处理程序,请使用带有异常捕获器的
而不是带有异常处理程序的
。这将避免无限循环

将异常对象转换为字符串可以通过以下方式完成:

(define (exception->string exc)
  (with-output-to-string
    (lambda ()
      (display-exception exc))))
它适用于
错误对象
和其他类型的异常,以及任何非异常对象

这是一个更便携的解决方案(经过表面测试):


使用Gambit获得无限循环的原因是变量
xxx
未绑定,因此异常处理程序
(lambda(e)(exit(错误对象消息e)))使用
未绑定全局异常
对象调用
,这会导致调用
错误对象消息
,但参数不是
错误对象
(该参数特定于调用
错误
过程引发的异常)因此,这会引发一个
类型异常
对象,导致调用相同的异常处理程序,以此类推

如果希望异常处理“弹出”当前异常处理程序,请使用带有异常捕获器的
而不是带有异常处理程序的
。这将避免无限循环

将异常对象转换为字符串可以通过以下方式完成:

(define (exception->string exc)
  (with-output-to-string
    (lambda ()
      (display-exception exc))))
它适用于
错误对象
和其他类型的异常,以及任何非异常对象

这是一个更便携的解决方案(经过表面测试):

对于Kawa: