我试图为Picolisp样式的let表达式编写一个宏,我们将其称为宏let-slim。为了更简洁(就像Picolisp),我希望在声明一个变量时,它们的用法类似于这样
(let-slim var-name initial-value
(display var-name))或者类似这样的东西来声明任意数量的变量(请注意,这是伪代码,我实际上不会包括省略号)
(let-slim (var-name-1 initital-value-1
var-name-2 initital-value-2
...
var-name-n initital-value-n)
(+ var-name-1 var-name-2 ... var-name-n))第一个使用程序编写syntax-rules匹配模式相当简单,但后者是我正在努力解决的问题。
这不起作用,因为只有init被重复
(define-syntax let-slim
(syntax-rules ()
[(_ (var init ...) body ...)
(let ((var init) ...)
body ... )]))这不起作用,因为它被认为是一个错误的省略
(define-syntax let-slim
(syntax-rules ()
[(_ (var ... init ...) body ...)
(let ((var init) ...)
body ... )]))这不起作用,因为我需要在参考点使用parens (这意味着与内置的let相比,它绝对没有什么变化)
(define-syntax let-slim
(syntax-rules ()
[(_ (var init) ...) body ...)
(let ((var init) ...)
body ... )]))那么,是否有一种方法可以在syntax-rules中重复两个变量,而不需要将它们封装在父类中,还是需要使用不同的宏系统(即syntax-case或defmacro)?
发布于 2019-06-02 23:29:50
在syntax-rules中这样做并不是最优的,但是由于它是图灵完成的,所以可以这样做:
(define-syntax let-slim
(syntax-rules (pair)
((_ pair bindings () body)
(let bindings . body))
((_ pair (acc ...) (k v . rest) body)
(let-slim pair (acc ... (k v)) rest body))
((_ (elements ...) . body)
(let-slim pair () (elements ...) body))))发布于 2019-06-02 22:00:32
使用语法规则...特性不可能一蹴而就,但您可能可以使用递归来使用语法规则:
(define-syntax let-slim
(syntax-rules ()
((let-slim (var-1 val-1 . rest) . body)
(let-slim var-1 val-1 (let-slim rest . body)))
((let-slim var val . body)
;; single binding case you already implemented
))唯一的问题是语法规则不能说明'var‘应该是一个符号。您将不会从这样的宏中获得很好的错误消息(例如,如果它与奇怪数量的var/val绑定一起使用)。用语法大小写实现这个宏可能更好。之所以难以实现,是因为它违背了对每个AST节点使用一对括号的想法。
https://stackoverflow.com/questions/56418999
复制相似问题