Racket参数化异常处理宏无法定位错误来源,求改进方案
修复Racket宏中错误追踪指向问题
你的问题根源在于:宏展开后,error表达式的语法位置绑定到了宏定义的位置,而非调用err的位置。要解决这个问题,只需要让error使用宏调用点的语法上下文来报告错误即可。
解决方案
利用Racketsyntax/parse提供的this-syntax标识符(代表当前宏调用的语法对象),直接将其传递给error函数,就能让错误追踪指向调用err的位置。
修改后的宏代码
(define-simple-macro (err param:id msg) (if (param) (error this-syntax msg) ; 传递调用点语法对象给error (display (format "Here be dragons: ~a\n" msg))))
完整测试代码
#lang racket (require syntax/parse/define) ;; 修复后的错误处理宏 (define-simple-macro (err param:id msg) (if (param) (error this-syntax msg) (display (format "Here be dragons: ~a\n" msg)))) ;; 模拟问题过程 (define (bad-thing?) #t) ; 修正原代码的thunk问题,原代码返回thunk会导致条件永远为真 (define SAFE (make-parameter #t)) ;; 打印警告 (parameterize ([SAFE #f]) (when (bad-thing?) (err SAFE "better watch out."))) ;; 触发错误,此时错误追踪会指向这一行的err调用 (when (bad-thing?) (err SAFE "Hell's bells, an exception has occurred!"))
说明
this-syntax是syntax/parse宏的内置标识符,保存了整个err调用语句的语法信息(包括行号、位置)。- 把
this-syntax传给error后,Racket会用这个位置生成错误追踪信息,替代原本宏定义处的位置。 - 原代码中
(bad-thing?)返回的是thunk对象,这会导致when条件永远为真(非#f值),因此修正为直接返回#t,让逻辑符合预期。
内容的提问来源于stack exchange,提问作者Tom Price
相关产品推荐
相关产品推荐

