短反引号和长反引号之间似乎存在一些差异.
(let ((x 123))
(dolist (res (list `(a `(b ,x))
`(a (backquote (b ,x)))
(backquote (a (backquote (b ,x))))
(backquote (a `(b ,x)))))
(print res)))
Run Code Online (Sandbox Code Playgroud)
输出:
(a (\` (b (\, x))))
(a (backquote (b 123)))
(a (backquote (b 123)))
(a (\` (b (\, x))))
Run Code Online (Sandbox Code Playgroud)
为什么它对x的行为有所不同?甚至不确定四个结果中的哪两个应该是令人惊讶的结果.
我不确定它是一个错误还是一个功能,主要是因为我不确定 elisp 程序员是否被允许/良好的做法来使用该函数backquote,或者它只是定义该函数的一种便捷方式。正确的输出是第一个(和第四个)输出。backquote查看(in )的代码,backquote.el很明显,backquote` 或 内的任何内容backquote都未正确扩展。相关代码是:
((eq (car s) backquote-backquote-symbol)
(backquote-delay-process s (1+ level)))
Run Code Online (Sandbox Code Playgroud)
其中backquote-backquote-symbol之前定义为“\”(引号-反斜杠-反引号)。有多种方法可以处理此错误,但该行可能是:
((or (eq (car s) backquote-backquote-symbol)
(eq (car s) 'backquote))
(backquote-delay-process s (1+ level)))
Run Code Online (Sandbox Code Playgroud)
(或使用任何其他变量来指定反引号非别名符号)。
编辑:更仔细地观察,还有另一个地方您也必须添加该测试,但这包括报告补丁。我看看我该怎么做。随着这一变化:
ELISP> (macroexpand-all `(a (backquote (b ,x))))
(a
(list 'b x))
ELISP> (macroexpand-all `(a `(b ,x)))
(a
(list 'b x))
Run Code Online (Sandbox Code Playgroud)