对于支持 R5RS 的方案实现,可以通过 syntax-rule 中的模式匹配来定义宏,在这种情况下为什么需要反引号?
我通过 emacs lisp 学习了一些非常基本的 lisp,在 elisp 中我们必须使用大量的反引号来编写宏,但是对于支持模式匹配的方案,在任何情况下使用反引号会有用吗?或者我应该问在什么情况下计划者通常会使用反引号来帮助他们解决问题?
Quasiquote(即反引号)只是运行时列表构造的语法糖。
这也是一个非常有用的。首先,它为您提供了明显的快速列表构造,使您可以快速从评估转移到报价上下文。
例如,代码(cons (append (list a 'b) c) d))
可以写成`(,a b ,@c ,@d)
(unquote-splicing,表示,@
为用于附加从表达式产生的列表)。
其次,它允许非常快速地跟踪调试一段代码。假设您有以下代码:
(define string-split
(lambda (s delim)
(reverse (car (fold-left
(lambda (p ch)
(let ((str-lst (car p))
(char-lst (cdr p)))
(if (char=? ch delim)
(if (null? char-lst)
(cons str-lst '())
(cons (cons (list->string (reverse char-lst)) str-lst) '()))
(cons str-lst (cons ch char-lst)))))
`(() ())
(append (string->list s) `(,delim)))))))
如果你用参数"abc def"
和调用它#\space
,你会从list->string
. 很难看出哪里出了问题,但如果你对调用进行 quasiquote并取消引用list->string
(使用,
)参数char-lst
,它会给你一个很好的开始提示。
反引号在“模板化”中非常有用。举个简单的例子,假设我想构造一个类似 html 的元素,其中包含一个无序列表,其第二个元素来自一个名为placeholder
. 我会这样写:
`(ul (li "the first item")
(li ,placeholder)
(li "the third item"))
你让它看起来我们制作列表的唯一时间是生成代码。不是这种情况。
反引号语法只是一些文字和一些扩展的语法糖。所以不要写:
(list 'this 'is expr)
你可以写
`(this is ,expr)
它们具有几乎相同的目标代码。因此,回答您的问题:如果您要生成一个列表或树(列表列表),其中包含文字部分和非文字部分,使用backquote
并将unquote
代码大大简化为更易于阅读的内容再次减少错误。
顺便说一句:由于syntax-rules
有限制,大多数实现至少有一个替代宏系统,它可能有quasiquote
unquote
甚至一个特殊版本的语法。从 R6RSsyntax-case
有#`
和#,
。