',(引号)在普通 lisp 中

Mic*_*ini 3 escaping common-lisp quoting backquote

',lisp 中反引号表达式的作用和用途是什么?它有名字吗?它是否记录在某处?它有多普遍和有用?

例如:

(defmacro test-exp (exp)
  `(format t "~&~S => ~S~%" ',exp ,exp))
Run Code Online (Sandbox Code Playgroud)

我的猜测是exp,在宏扩展时,它将采用字面上的任何内容,并',exp用它替换。(与评估exp和替换,exp它相反)。

cor*_*ump 7

你猜对了。

引用

特殊运算符quote定义了一个表达式,该表达式字面意思计算为其子形式。例如:

(quote (looks like a function call))
Run Code Online (Sandbox Code Playgroud)

内部形式看起来像一个函数调用,但对于 Lisp 读者来说,这只是一个符号列表。表达式(quote ...)计算该列表,而不尝试将列表计算为代码。

引用表达式有特殊的语法,即引号字符,因此'exp(quote exp). 当您不想评估它们时,这通常是您编写符号的方式。

反引号/逗号

Quasiquotation 是一种只引用表达式的一部分的方法。

反引号的作用类似于引号:不评估其中的数据,除非它们以逗号为前缀,在这种情况下,评估会重新打开。下面的表达式

`(format t "~s" ,exp)
Run Code Online (Sandbox Code Playgroud)

……可以写成:

(list 'format 't '"~s" exp)
Run Code Online (Sandbox Code Playgroud)

为了完整性,我在文字之前添加了引号,否则会自我评估,但在实践中,您将编写如下相同的列表:

(list 'format t "~s" exp)
Run Code Online (Sandbox Code Playgroud)

Hereexp被评估,并且整个表单给出一个类似于对 的调用的列表format, whereenv被替换为它的任何值。

引用逗号

您在示例中看到的引号/逗号组合是一个常见的习惯用法,您希望将在宏扩展时给出的参数(即代码)按字面意思放入正在扩展的代码中,而不对其进行评估。如果您通过宏扩展来测试您的宏,您可以看到结果代码:

(macroexpand '(test-exp (+ 5 8)))

=> (FORMAT T "~&~S => ~S~%" '(+ 5 8) (+ 5 8))
Run Code Online (Sandbox Code Playgroud)

文字(+ 5 8)形式放置在(quote ...)形式中,使其在运行时不被评估。同时,相同的表达式按原样放置在它旁边,从而在运行时对其进行评估。如果您评估结果表达式,它会打印:

 (+ 5 8) => 13
Run Code Online (Sandbox Code Playgroud)