首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >嵌套省略宏在欺诈和球拍中不起作用

嵌套省略宏在欺诈和球拍中不起作用
EN

Stack Overflow用户
提问于 2021-08-11 11:47:27
回答 3查看 192关注 0票数 2

我正在尝试创建一个简单的嵌套宏。它在我的Scheme实现中工作,但是在欺骗和欺骗中运行失败。

代码语言:javascript
复制
(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跑,但那个只是抛出:

未绑定变量:定义-语法

我想你需要用一个库来使用一个基本的方案。

在“签入方案”中,更新省略号后:

代码语言:javascript
复制
(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

这个宏怎么了?为什么它会抛出一个错误?

编辑

这种模式似乎是无效的:

代码语言:javascript
复制
(_ x ...)

但这是

代码语言:javascript
复制
(_ x y ...)

这是什么地方指定的吗?为什么第一个语法无效?

为了完整起见,这段代码会编译,但是为什么第一段没有编译呢?

代码语言:javascript
复制
(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时。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-08-12 05:04:38

问题是省略号在外部宏中遵循x。这意味着所生成的模板也应该在x后面有省略号,但它没有。如果您将内部宏的x重命名为y,它应该会像您预期的那样工作。

换句话说,你在这里所做的相当于:

代码语言:javascript
复制
(define-syntax foo
  (syntax-rules ()
    ((_ x ...)
     (display x))))

也是不允许的。如果模式中有带有省略号的x,则在使用下面的模板中的x时,还必须使用这些省略号。

如果您使其为(x y ...),则它工作的原因是模板根本不使用y (及其省略rest)。

票数 1
EN

Stack Overflow用户

发布于 2021-08-11 14:06:37

外部语法中的模式(_ x ...) -规则将模式变量x绑定到匹配列表中。这意味着,当x出现在模板中时,必须后面跟着一个省略号(不一定是直接的)。

这就是为什么你会从诡计和球拍中得到错误。

现在考虑外部宏(foo)引入内部宏(bar)的情况,该宏的定义包含省略号。当扩展器看到...时,它属于外部还是内部宏定义?

使用的惯例(至少由Racket和所有语法派生的语法规则实现)是...属于外层。为了产生“内部省略”,需要“引用”。因此,生成一个内部省略号,编写(... ...)

在实践中,这可能很烦人,所以我经常将内部定义封装在

代码语言:javascript
复制
(with-syntax ((ooo (... ...))
 code using ooo as an inner ellipsis here)

据我所知,您的示例中的(syntax-rules <:::> () etc)是不标准的,因为语法是(syntax-rules literals (pattern template) ...)。因此,符号<:::>不允许作为文字列表。

票数 1
EN

Stack Overflow用户

发布于 2021-08-13 21:48:10

您的宏有几个问题。

  1. 重用内部宏模板中的词法宏绑定。x将在结果中展开,因此将尝试替换let-syntax中的(_ x),但是由于x模板有省略号,预计插入x的位置在某个地方有省略号。我不认为你的意思是这是相同的绑定,所以用任何其他符号取代它将修复它。例如:single

  1. 使用let-syntax意味着不能有使用相同语法规则的扩展,但是在第二种模式中,您可以打印第一个元素,然后再这样做。用letrec-syntax替换它将修复这个问题。

  1. 模式x ...匹配零或多个元素。因此,(foo)与模式匹配,但是bar没有兼容的模板。添加一个模式来捕获无操作数的情况修正了这个问题。

在球拍中不支持使用SRFI-46的

  1. .您根本不能指望它会被开箱即用,所以您需要在每个实现中检查它。在球拍中,您可以使用(... ...)作为替代。这与R6RS / R7RS也是一样的。

把这些拿进去,我就这样结束了。在球拍中效果很好:

代码语言:javascript
复制
(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 ...)))))

虽然我不知道如何简化您的示例,但可以用以下内容替换:

代码语言:javascript
复制
(define-syntax foo
  (syntax-rules ()
    ((_ x ...)
     (begin
       (begin
         (display x)
         (display " "))
       ...))))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68741400

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档