', (quote-comma) 在普通的 lisp 中
', (quote-comma) in common lisp
在 lisp 的反引号表达式中 ',
的作用和用途是什么?它有名字吗?它是否记录在某处?它有多普遍和有用?
例如:
(defmacro test-exp (exp)
`(format t "~&~S => ~S~%" ',exp ,exp))
我的猜测是,在这里它会在宏扩展时采用 exp
字面上的任何内容,并用它替换 ',exp
。 (与评估 exp
并用它替换 ,exp
相反)。
你猜对了。
引用
特殊运算符 quote
定义了一个表达式,按字面意思计算其子形式。例如:
(quote (looks like a function call))
内部形式看起来像一个函数调用,但对于 Lisp reader,这只是一个符号列表。表达式 (quote ...)
计算该列表,而不尝试将该列表计算为代码。
引用表达式有特殊语法,引号字符,因此'exp
与(quote exp)
相同。当您不想计算符号时,通常就是这样写的。
反引号/逗号
准引用是一种仅引用表达式的一部分的方法。
反引号的作用类似于引号:不会对其中的数据进行评估,除非它们以逗号为前缀,在这种情况下,评估会重新打开。
下面的表达式
`(format t "~s" ,exp)
...可以写成:
(list 'format 't '"~s" exp)
为了完整起见,我在文字前添加了引号,否则会自我评估,但实际上您会编写如下相同的列表:
(list 'format t "~s" exp)
这里 exp
被评估,整个表格给出了一个列表,该列表类似于对 format
的调用,其中 env
被替换为它的值。
引用逗号
您在示例中看到的 quote/comma 组合是一个常见的习语,您希望将在宏展开时给出的参数(即代码)按字面意思放入要展开的代码中,而不对其求值。如果您通过宏扩展来测试您的宏,您可以看到结果代码:
(macroexpand '(test-exp (+ 5 8)))
=> (FORMAT T "~&~S => ~S~%" '(+ 5 8) (+ 5 8))
文字 (+ 5 8)
形式被放置在 (quote ...)
形式中,使其在运行时不被评估。同时,相同的表达式按原样放在它旁边,从而在运行时对其进行评估。如果计算结果表达式,它会打印:
(+ 5 8) => 13
',
只能用在反引号表达式中。它们是两个不同的 reader 宏 '
用于引用和 ,
用于反引号 s 表达式中的计算。逗号只能出现在反引号表达式中。
`(a ',(+ 1 2))
以上同
`(a (QUOTE ,(+ 1 2)))
因为 '
是 quote
的 reader 宏。
因此它具有与以下类似的效果:
(list (quote a) (list (quote quote) (+ 1 2)))
计算结果为
(A (QUOTE 3))
比较
`(a ',(+ 1 2))
与评估结果
(A (QUOTE 3))
基本上引用了(+ 1 2)
的评估结果,并将其包含在列表中。
在 lisp 的反引号表达式中 ',
的作用和用途是什么?它有名字吗?它是否记录在某处?它有多普遍和有用?
例如:
(defmacro test-exp (exp)
`(format t "~&~S => ~S~%" ',exp ,exp))
我的猜测是,在这里它会在宏扩展时采用 exp
字面上的任何内容,并用它替换 ',exp
。 (与评估 exp
并用它替换 ,exp
相反)。
你猜对了。
引用
特殊运算符 quote
定义了一个表达式,按字面意思计算其子形式。例如:
(quote (looks like a function call))
内部形式看起来像一个函数调用,但对于 Lisp reader,这只是一个符号列表。表达式 (quote ...)
计算该列表,而不尝试将该列表计算为代码。
引用表达式有特殊语法,引号字符,因此'exp
与(quote exp)
相同。当您不想计算符号时,通常就是这样写的。
反引号/逗号
准引用是一种仅引用表达式的一部分的方法。
反引号的作用类似于引号:不会对其中的数据进行评估,除非它们以逗号为前缀,在这种情况下,评估会重新打开。 下面的表达式
`(format t "~s" ,exp)
...可以写成:
(list 'format 't '"~s" exp)
为了完整起见,我在文字前添加了引号,否则会自我评估,但实际上您会编写如下相同的列表:
(list 'format t "~s" exp)
这里 exp
被评估,整个表格给出了一个列表,该列表类似于对 format
的调用,其中 env
被替换为它的值。
引用逗号
您在示例中看到的 quote/comma 组合是一个常见的习语,您希望将在宏展开时给出的参数(即代码)按字面意思放入要展开的代码中,而不对其求值。如果您通过宏扩展来测试您的宏,您可以看到结果代码:
(macroexpand '(test-exp (+ 5 8)))
=> (FORMAT T "~&~S => ~S~%" '(+ 5 8) (+ 5 8))
文字 (+ 5 8)
形式被放置在 (quote ...)
形式中,使其在运行时不被评估。同时,相同的表达式按原样放在它旁边,从而在运行时对其进行评估。如果计算结果表达式,它会打印:
(+ 5 8) => 13
',
只能用在反引号表达式中。它们是两个不同的 reader 宏 '
用于引用和 ,
用于反引号 s 表达式中的计算。逗号只能出现在反引号表达式中。
`(a ',(+ 1 2))
以上同
`(a (QUOTE ,(+ 1 2)))
因为 '
是 quote
的 reader 宏。
因此它具有与以下类似的效果:
(list (quote a) (list (quote quote) (+ 1 2)))
计算结果为
(A (QUOTE 3))
比较
`(a ',(+ 1 2))
与评估结果
(A (QUOTE 3))
基本上引用了(+ 1 2)
的评估结果,并将其包含在列表中。