首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在方案中显示来自eval的错误消息?

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

Stack Overflow用户
提问于 2021-01-11 12:43:25
回答 3查看 284关注 0票数 1

我试图创建计算表达式并将错误作为字符串返回错误的代码:

代码语言:javascript
复制
(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)

  • Gauche

  • 欺骗消息Unbound variable: ~S如何获得实际错误消息而不是模板?

  • Kawa异常:

  • 内核转储

  • Gambit冻结

注意:这是REPL的一部分,我正在系统上的所有Scheme实现中进行测试。它几乎可以工作,它可以自己运行,但是我想在异常发生时显示正确的错误消息,而不是退出REPL。

EN

回答 3

Stack Overflow用户

发布于 2021-01-11 23:34:20

Gauche堆芯

糟了。当然,这并不理想,但可以解释。

默认情况下,由于历史原因,

  • with-exception-handler是SRFI-18,而不是R7RS。这意味着异常处理程序是在异常发生的动态环境中调用的,包括异常处理程序设置。如果异常处理程序中发生异常,则调用相同的异常处理程序,从而导致无限递归。显然,Gauche的运行时耗尽了C堆栈,或者something.
  • error-object-message没有在Gauche的默认名称空间中定义。因此,这首先触发了一个异常。

添加

代码语言:javascript
复制
(import (scheme base) (scheme write) (scheme r5rs))

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

代码语言:javascript
复制
unbound variable: xxx 

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

编辑IMHO,with-exception-handler应该被认为是构建易于使用的实用程序的最低层结构,因此应该格外小心地使用。在一般用例中,guard提供了一个很好的抽象。

票数 1
EN

Stack Overflow用户

发布于 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以这种方式将异常对象转换为字符串:

代码语言:javascript
复制
(define (exception->string exc)
  (with-output-to-string
    (lambda ()
      (display-exception exc))))

它适用于error-objects和其他类型的异常,以及任何非异常对象.

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

代码语言:javascript
复制
(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)
票数 1
EN

Stack Overflow用户

发布于 2021-01-14 08:49:21

对Kawa来说:

代码语言:javascript
复制
   (define (exception->string exc)
     (call-with-port (open-output-string)
                     (lambda (port)
                       (display exc port)
                       (get-output-string port)))))

这将将异常转换为字符串并获得错误消息。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65667115

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档