我的 Racket 异常处理宏找不到错误源

My Racket exception handling macro does not locate source of error

提问人:Tom Price 提问时间:11/10/2023 最后编辑:Tom Price 更新时间:11/10/2023 访问量:44

问:

我正在尝试实现参数化错误处理。如果发生错误且参数 SAFE 为 true,则会引发错误,程序将停止。但是,如果 SAFE 为 false,则会打印警告并继续程序。

#lang racket
(require syntax/parse/define)

;; raises parameterized error message
(define-simple-macro
  (err param:id msg)
  (if (param)
      (error msg)
      (display (format "Here be dragons: ~a\n" msg))))

;; a problematic procedure
(define (bad-thing?) (thunk #t))

;; default value of SAFE = #t
(define SAFE (make-parameter #t))

;; prints warning
(parameterize ([SAFE #f])
  (when (bad-thing?)
    (err SAFE "better watch out.")))

;; raises error
(when (bad-thing?)
  (err SAFE "Hell's bells, an exception has occurred!"))

宏的问题在于,当引发错误时,它会追溯到定义宏的位置,而不是调用有问题的过程的位置。errbad-thing?

一定有更好的方法!有人能给我指出正确的方向吗?

异常 错误处理 球拍

评论

0赞 Peter Winton 11/10/2023
如果您更改为普通程序,它是否按照您想要的方式工作?err
0赞 Tom Price 11/10/2023
(define (err param msg) (if (param) ...给出的结果大致相同。
0赞 Peter Winton 11/10/2023
因此,该行为并非特定于宏。即使您将最后一个表达式包装在过程中并调用它,您也可能无法获得该过程的堆栈帧,因为调用将处于尾部位置并且可能会被优化。考虑传递“who-sym”(请参阅文档),而不是依赖堆栈跟踪作为上下文。(when (bad-thing?) ...)errerror
0赞 Tom Price 11/10/2023
嗯。在文档中找不到任何关于“who-sym”的内容。
1赞 Shawn 11/10/2023
docs.racket-lang.org/reference/......

答:

2赞 Shawn 11/10/2023 #1

如果使用基包装器而不是更高级别的包装器来获取表示宏调用站点的语法对象,则可以包装 in syntax/loc 以使该位置显示为:syntax-parseerror

#lang racket
(require (for-syntax syntax/parse))

;; raises parameterized error message
(define-syntax (err stx)
  (syntax-parse stx
    [(err param:id msg)
     #`(if (param)
         #,(syntax/loc stx (error msg))
         (display (format "Here be dragons: ~a\n" msg)))]))

;; a problematic procedure
(define (bad-thing?) (thunk #t))

;; default value of SAFE = #t
(define SAFE (make-parameter #t))

;; prints warning
(parameterize ([SAFE #f])
  (when (bad-thing?)
    (err SAFE "better watch out.")))

;; raises error
(when (bad-thing?)
  (err SAFE "Hell's bells, an exception has occurred!"))

评论

0赞 Tom Price 11/11/2023
完善。谢谢!