3

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

例如:

(defmacro test-exp (exp)
  `(format t "~&~S => ~S~%" ',exp ,exp))

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

4

2 回答 2

7

你猜对了。

引用

特殊运算符定义quote了一个表达式,该表达式从字面上看是其子形式。例如:

(quote (looks like a function call))

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

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

反引号/逗号

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

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

`(format t "~s" ,exp)

...可以写成:

(list 'format 't '"~s" exp)

为了完整起见,我在文字之前添加了引号,否则它们会自我评估,但实际上你会编写如下相同的列表:

(list 'format t "~s" exp)

这里exp被评估,整个表单给出了一个类似于调用的列表format,其中env被替换为它的值。

引用逗号

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

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

=> (FORMAT T "~&~S => ~S~%" '(+ 5 8) (+ 5 8))

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

 (+ 5 8) => 13
于 2020-02-24T15:11:40.277 回答
3

',只能在反引号表达式中使用。它们是两个不同的读取器宏,用于在反引号 s 表达式中'引用和,评估。逗号只能出现在反引号表达式中。

`(a ',(+ 1 2))

上面是一样的

`(a (QUOTE ,(+ 1 2)))

因为'是一个阅读器宏quote

因此,它具有与以下类似的效果:

(list (quote a) (list (quote quote) (+ 1 2)))

评估为

(A (QUOTE 3))

相比

`(a ',(+ 1 2))

与评估结果

(A (QUOTE 3))

它基本上引用了评估结果(+ 1 2)并将其包含在列表中。

于 2020-02-24T16:22:31.323 回答