',
lisp中反引号表达式的作用和用途是什么?它有名字吗?它是否记录在某个地方?它有多普遍和有用?
例如:
(defmacro test-exp (exp)
`(format t "~&~S => ~S~%" ',exp ,exp))
我的猜测是,在这里它将exp
在宏扩展时采用字面上的任何内容,并',exp
用它替换。(与评估exp
和替换,exp
它相反)。
',
lisp中反引号表达式的作用和用途是什么?它有名字吗?它是否记录在某个地方?它有多普遍和有用?
例如:
(defmacro test-exp (exp)
`(format t "~&~S => ~S~%" ',exp ,exp))
我的猜测是,在这里它将exp
在宏扩展时采用字面上的任何内容,并',exp
用它替换。(与评估exp
和替换,exp
它相反)。
你猜对了。
特殊运算符定义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
',
只能在反引号表达式中使用。它们是两个不同的读取器宏,用于在反引号 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)
并将其包含在列表中。