我正在尝试创建一个简单的嵌套宏。它在我的Scheme实现中工作,但是在欺骗和欺骗中运行失败。
(define-syntax foo
(syntax-rules (:c)
((_ x ...)
(let-syntax ((bar (syntax-rules ::: (:c)
((_ x)
(print x))
((_ a b :::)
(begin
(display a)
(display " ")
(bar b :::))))))
(bar x ...)))))语法:省略省略号
模板中含有模式变量的
缺失省略
我也试过在Gambit跑,但那个只是抛出:
未绑定变量:定义-语法
我想你需要用一个库来使用一个基本的方案。
在“签入方案”中,更新省略号后:
(define-syntax foo
(syntax-rules (:c)
((_ x ...)
(let-syntax ((bar (syntax-rules <:::> (:c)
((_ x)
(print x))
((_ a b <:::>)
(begin
(display a)
(display " ")
(bar b <:::>))))))
(bar x ...)))))投掷:
模板尺寸误差(椭圆太少?):x
这个宏怎么了?为什么它会抛出一个错误?
编辑
这种模式似乎是无效的:
(_ x ...)但这是
(_ x y ...)这是什么地方指定的吗?为什么第一个语法无效?
为了完整起见,这段代码会编译,但是为什么第一段没有编译呢?
(define-syntax foo
(syntax-rules ()
((_ x y ...)
(let-syntax ((bar (syntax-rules <:::> ()
((_ x)
(print x))
((_ a b <:::>)
(begin
(display a)
(display " ")
(bar b <:::>))))))
(bar x y ...)))))但是当尝试使用foo宏时,它不起作用。它抛出:
无界变量: bar
即使在使用letrec-syntax时。
发布于 2021-08-12 05:04:38
问题是省略号在外部宏中遵循x。这意味着所生成的模板也应该在x后面有省略号,但它没有。如果您将内部宏的x重命名为y,它应该会像您预期的那样工作。
换句话说,你在这里所做的相当于:
(define-syntax foo
(syntax-rules ()
((_ x ...)
(display x))))也是不允许的。如果模式中有带有省略号的x,则在使用下面的模板中的x时,还必须使用这些省略号。
如果您使其为(x y ...),则它工作的原因是模板根本不使用y (及其省略rest)。
发布于 2021-08-11 14:06:37
外部语法中的模式(_ x ...) -规则将模式变量x绑定到匹配列表中。这意味着,当x出现在模板中时,必须后面跟着一个省略号(不一定是直接的)。
这就是为什么你会从诡计和球拍中得到错误。
现在考虑外部宏(foo)引入内部宏(bar)的情况,该宏的定义包含省略号。当扩展器看到...时,它属于外部还是内部宏定义?
使用的惯例(至少由Racket和所有语法派生的语法规则实现)是...属于外层。为了产生“内部省略”,需要“引用”。因此,生成一个内部省略号,编写(... ...)。
在实践中,这可能很烦人,所以我经常将内部定义封装在
(with-syntax ((ooo (... ...))
code using ooo as an inner ellipsis here)据我所知,您的示例中的(syntax-rules <:::> () etc)是不标准的,因为语法是(syntax-rules literals (pattern template) ...)。因此,符号<:::>不允许作为文字列表。
发布于 2021-08-13 21:48:10
您的宏有几个问题。
x将在结果中展开,因此将尝试替换let-syntax中的(_ x),但是由于x模板有省略号,预计插入x的位置在某个地方有省略号。我不认为你的意思是这是相同的绑定,所以用任何其他符号取代它将修复它。例如:singlelet-syntax意味着不能有使用相同语法规则的扩展,但是在第二种模式中,您可以打印第一个元素,然后再这样做。用letrec-syntax替换它将修复这个问题。x ...匹配零或多个元素。因此,(foo)与模式匹配,但是bar没有兼容的模板。添加一个模式来捕获无操作数的情况修正了这个问题。在球拍中不支持使用SRFI-46的
(... ...)作为替代。这与R6RS / R7RS也是一样的。把这些拿进去,我就这样结束了。在球拍中效果很好:
(define-syntax foo
(syntax-rules (:c)
((_) (begin)) ; or you may signal an error
((_ x...)
(letrec-syntax ((bar (syntax-rules (:c)
((_ single)
(print single))
((_ first rest (... ...))
(begin
(display first)
(display " ")
(bar rest (... ...)))))))
(bar x ...)))))虽然我不知道如何简化您的示例,但可以用以下内容替换:
(define-syntax foo
(syntax-rules ()
((_ x ...)
(begin
(begin
(display x)
(display " "))
...))))https://stackoverflow.com/questions/68741400
复制相似问题