对于支持R5RS的方案实现,可以通过语法规则中的模式匹配来定义宏,在这种情况下,为什么需要反引号?
我通过emacs lisp学习了一些非常基本的lisp,在elisp中,我们必须使用大量的反引号来编写宏,但是对于支持模式匹配的方案,有没有使用反引号的情况?还是我应该问计划者在什么情况下通常会使用反引号来帮助他们解决问题?
答案 0 :(得分:2)
反引号对于“模板化”非常有用。举一个简单的例子,假设我要构造一个类似html的元素,其中包含一个无序列表,其第二个元素来自名为placeholder
的程序变量。我会这样写:
`(ul (li "the first item")
(li ,placeholder)
(li "the third item"))
答案 1 :(得分:2)
Quasiquote(即反引号)只是用于运行时列表构建的语法suger。
这也是非常有用的。首先,它为您提供了明显的快速列表构造,使您可以从评估快速转到报价上下文。
例如,代码(cons (append (list a 'b) c) d))
可以写为`(,a b ,@c ,@d)
(用,@
表示的非引号拼写用于附加由表达式得出的列表)。
第二,它允许非常快速地跟踪调试一段代码。假设您有以下代码:
(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
中收到错误消息。很难看到哪里出了问题,但是如果您对list->string
的调用进行了半引用,并取消了,
的引用(使用char-lst
),它将为您提供一个很好的提示开始。
答案 2 :(得分:1)
您似乎使我们唯一一次列出列表是为了生成代码。不是这种情况。
反引号语法只是某些文字和某些扩展的语法糖。所以不用写:
(list 'this 'is expr)
你可以写
`(this is ,expr)
这些具有几乎相同的目标代码。因此,回答您一个问题:如果要生成一个列表或树(列表的列表),其中包含部分为文字的部分,某些部分不是文字的部分,则使用backquote
和unquote
可以大大简化代码变得更易于阅读,从而减少了错误。
BTW:由于syntax-rules
有局限性,因此大多数实现都有至少一个替代宏系统,并且可能具有quasiquote
unquote
甚至是语法的特殊版本。 syntax-case
在R6RS中具有#`
和#,
。