短反引号和长反引号之间似乎存在一些差异。
(let ((x 123))
(dolist (res (list `(a `(b ,x))
`(a (backquote (b ,x)))
(backquote (a (backquote (b ,x))))
(backquote (a `(b ,x)))))
(print res)))
输出:
(a (\` (b (\, x))))
(a (backquote (b 123)))
(a (backquote (b 123)))
(a (\` (b (\, x))))
为什么它的行为与x不同?甚至不确定四个结果中的哪两个应该是令人惊讶的结果。
答案 0 :(得分:3)
我不确定它是不是一个bug或一个功能,主要是因为我不确定elisp程序员是否被允许/良好练习使用backquote
功能,或者它只是一种方便的方式定义功能。正确的输出是第一(和第四)输出。查看backquote
的代码(在backquote.el
中)很明显,`或backquote
内的任何backquote
都未正确展开。相关的代码是:
((eq (car s) backquote-backquote-symbol)
(backquote-delay-process s (1+ level)))
其中backquote-backquote-symbol
之前定义为'\`(quote-backslash-backtick)。有几种方法可以处理这个错误,但那一行可能是:
((or (eq (car s) backquote-backquote-symbol)
(eq (car s) 'backquote))
(backquote-delay-process s (1+ level)))
(或使用任何其他变量来指定反引号未混淆符号)。
编辑:仔细观察,还有另一个地方你必须添加该测试,但这包括报告补丁。我会看到我该怎么做。随着这种变化:
ELISP> (macroexpand-all `(a (backquote (b ,x))))
(a
(list 'b x))
ELISP> (macroexpand-all `(a `(b ,x)))
(a
(list 'b x))