从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
在示例中匹配的是什么,为什么没有捕获到一个示例?
答案 0 :(得分:1)
通常尾部匹配列表的其余部分,例如
表示'(1 2 3 4)与模式(1.x)匹配,x匹配'(2 3 4)。
结果令人困惑,所以需要到源头查看实现(参见ice-9 / psyntax.scm)
可以看到省略号被转换为(每个+ x y z),在这种情况下,z是尾部,并且匹配最后一个cdr,在所有情况下都是'()。
在示例中...是gready和。尾巴不是。如果您对如何记录此行为感到不满意或想要更改实现,您可以在guile-devel邮件列表中询问:guile-devel@gnu.org
Guile还将语法分析作为可下载的lib(搜索guile-syntax-parse),这是几年前racket语法分析的一个端口(如果你很好奇,请参阅racket的文档)我编写了你的代码使用syntax-parse并按预期执行的示例。