如何修改Racket的define-as-symbols宏以忽略最后一个斜杠前的参数?
修改Racket的
define-as-symbols宏以支持忽略斜杠前的参数 原有的define-as-symbols宏可以直接定义一批与符号同名的变量,变量值就是对应的符号本身:
(define-syntax-rule (define-as-symbols args ...) (define-values (args ...) (apply values (quote (args ...))))) ; 原用法示例 (define-as-symbols A B C) (println A) ; -> 'A (println B) ; -> 'B (println C) ; -> 'C
现在需要扩展这个宏,支持形如(define-as-symbols ignore / ignore / A B C)的调用——忽略最后一个/之前的所有参数,只定义后面的A、B、C为对应符号。
修改后的宏实现
我们可以用syntax-rules的递归匹配来实现这个需求:
(define-syntax define-as-symbols (syntax-rules (/) ; 基础模式:没有斜杠时,直接定义所有参数为对应符号 [(_ args ...) (define-values (args ...) (apply values (quote (args ...))))] ; 递归模式:跳过当前斜杠及之前的内容,处理剩余部分 [(_ prefix ... / rest ...) (define-as-symbols rest ...)]))
工作原理
- 宏通过
syntax-rules指定/为特殊匹配符号 - 遇到包含
/的调用时,会递归地丢弃/及其前面的所有参数,直到处理到最后一组无/的参数 - 最后触发基础模式,把剩余的参数定义为对应符号的变量
测试示例
; 新用法测试 (define-as-symbols ignore / ignore / A B C) (println A) ; -> 'A (println B) ; -> 'B (println C) ; -> 'C ; 保留原有用法的兼容性 (define-as-symbols X Y) (println X) ; -> 'X (println Y) ; -> 'Y
内容的提问来源于stack exchange,提问作者tehkonst
相关产品推荐
相关产品推荐

