【问题标题】:Scheme macro what does match what?Scheme宏什么匹配什么?
【发布时间】:2018-05-21 20:49:44
【问题描述】:

来自https://www.gnu.org/software/guile/manual/html_node/Syntax-Rules.html#Syntax-Rules我得到了以下宏示例:

(define-syntax simple-let
  (syntax-rules ()
    ((_ (head ... ((x . y) val) . tail)
        body1 body2 ...)
     (syntax-error
      "expected an identifier but got"
      (x . y)))
    ((_ ((name val) ...) body1 body2 ...)
     ((lambda (name ...) body1 body2 ...)
      val ...))))

我正在尝试了解此宏的工作原理。所以我稍微注释了一下:

;; EXAMPLE 7
;; Reporting errors at macro-expansion time (read time, compile time).
(define-syntax simple-let
  (syntax-rules ()
    [(simple-let (head ... ((x . y) val) . tail)
                                        ; (1) head ... can also be zero times?
                                        ; (2) what is `. tail` matching?
                                        ; (3) can I not use two ellipsis on the
                                        ; same level instead of `. tail`?
                 body1
                 body2 ...)
     (syntax-error "expected an identifier but got"
                   (x . y))]
    ;; if there ((a . b) val) is not matched
    [(simple-let ((name val) ...)
                 body1
                 body2 ...)
     ((lambda (name ...)
        body1
        body2 ...)
      val ...)]))

就它的工作原理而言,我唯一不明白的部分是第一个匹配表达式:

(simple-let (head ... ((x . y) val) . tail)

所以我尝试了几个例子:

;; simply working
(simple-let ([a 3])
            (+ a 4))

;; caught
(simple-let ([(a . b) 3])  ; Q: What is `. tail` matching in this one?
            (+ a 4))
(simple-let ([a 3] [(b . c) 3])  ; Q: What is `. tail` matching in this one?
            (+ a b))

;; not caught
(simple-let ([a 3] [(b . c) 3] [d 4])  ; Q: Why is `. tail` not matching `[d 4]`?
            (+ a b))

我很难理解. tail 匹配的部分以及原因。我尝试使用... 而不是. 并将其放在tail 后面,以便捕获未捕获语法错误的示例,因为它没有进入第一个匹配案例,但它不起作用并且告诉我这是省略号的错误用法。我的猜测是,在同一嵌套级别中不能有两个省略号,因为很难知道哪个省略号匹配什么。有点像正则表达式在某些情况下的计算成本很高。

那么. tail 在示例中匹配什么,为什么没有捕获到那个示例?

【问题讨论】:

    标签: macros scheme matching


    【解决方案1】:

    通常tail匹配列表的其余部分,例如

    对于 '(1 2 3 4) 匹配模式 (1 . x),x 匹配 '(2 3 4)。

    结果令人困惑,因此需要查看源代码以查看实现(请参阅 ice-9/psyntax.scm)

    可以看到省略号被转换为 (each+ x y z),在这种情况下 z 是 tail 并且匹配最后一个 cdr,在所有情况下都是 '()。

    在示例中 ... 是 gready 并且 .尾巴不是。如果您对这种行为的记录方式不满意或想要更改实现,您可以在 guile-devel 邮件列表中询问:guile-devel@gnu.org

    Guile 还将语法解析作为可下载的库(搜索 guile-syntax-parse),这是几年前球拍的语法解析的一个端口(如果你好奇,请参阅球拍的文档)我编写了你的带有语法解析的示例,并按照您的预期执行。

    【讨论】:

    • 与其他一些在线资源相比,我发现 Guile 文档中的示例很好地解释了,除了那一件事。很高兴知道方案之间存在如此细微的差异。我天真地认为行为会是相同的,因为 Guile 和 Racket 符合某些 RnRS,但也许这些 RnRS 中没有指定这方面。
    猜你喜欢
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    • 2017-10-04
    • 2018-06-18
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多