能否将拼接语法封装为syntax-class以保留与直接使用一致的调用形式
解决方案
修改bindings语法类的匹配规则即可,把原本匹配单个数组结构的模式改为匹配连续语法序列的模式:
(begin-for-syntax (define-splicing-syntax-class bindings ;; ~seq 表示匹配连续的多个 bind 项,不需要外层包裹括号 (pattern (~seq b*:bind ...))) (define-syntax-class bind #:datum-literals (:) (pattern (name:id : ty)))) (define-syntax-parser def2 [(_ name:id b*:bindings) #''ok]) ;; 现在可以直接使用无外层括号的调用形式 (def2 a [a : Num] [b : Num])
原理解释
- 你最初定义的
bindings虽然是拼接语法类,但pattern写的是(b*:bind ...),代表匹配单个列表形式,列表内部才是多个bind项,所以调用时必须套一层括号才能匹配成功。 - 替换为
(~seq b*:bind ...)后,~seq是Racket模式匹配中的序列匹配关键字,会让这个拼接语法类直接匹配零个或多个连续的bind项,不需要额外的外层括号包裹,效果和你直接写b*:bind ...完全一致,同时还把匹配逻辑封装到了bindings语法类中,后续你可以直接在展开逻辑里通过b*.name获取所有绑定的标识符、b*.ty获取所有对应类型,和原来的使用习惯没有区别。
内容的提问来源于stack exchange,提问作者林子篆
相关产品推荐
相关产品推荐

