[英]Common Lisp Double-Backquote, Unquote, Quote, Unquote sequence?
我正在阅读Let Over Lambda,它涉及一些非常深层次的宏创作。 它很吸引人,而且我主要是为了跟上它。
在第4章中,Hoyte实现了用于CL-PPCRE匹配和替换函数的读取器宏,这样您就可以执行以下操作:
(#~m/(foo|bar)\d+/ "Some foo99") ; matches!
(#~s/foo(\d+)/bar\1/, "Some foo99") ; "Some bar99
为了实现这一点,我们定义了一个使用双反引号的宏,因为它实际上是由一个包装宏扩展的,它需要引用的值(它返回一个lambda形式)。 在准引用列表中,有一些使用以下序列,',varname
,我无法,',varname
。 什么是最初的,'
在这做什么?
(defmacro! pcre/match-lambda-form (o!args)
"Expands to a lambda that applies CL-PPCRE:SCAN"
``(lambda (,',g!str)
(cl-ppcre:scan ,(car ,g!args)
,',g!str)))
实际上,如果你没有读过这本书,我可能会更好地将其提炼成只使用defmacro
东西。 str
是一个符号, args
是一个列表:
(defmacro pcre/match-lambda-form (args)
"Expands to a lambda that applies CL-PPCRE:SCAN"
``(lambda (,',str)
(cl-ppcre:scan ,(car ,args)
,',str)))
引号基本上是双引用内部部分,因此结果可以不加引号两次? 有效地将'str
放入扩展形式,而不仅仅是str
?
编辑| 感谢Terje D.和一些在REPL中玩游戏,这几乎是这样的情况:
(defvar a 42)
(equal ``(,,a) '(list 42)) ; T
(equal ``(,a) '(list a)) ; T
(equal ``(,',a) ''(42)) ; T
(equal ``(a) ''(a)) ; T (obviously)
所以:
在评估双重反引号形式期间,首先处理内部反引号,结果是单独反引号形式。 在评估内部反引号形式期间,仅评估前面有两个逗号的元素。 然而,评估这些双重未引用元素的结果仍然(单独)不加引号,因此在评估得到的单一反引号形式时再次对其进行评估。 为了仅在内部反引号形式中进行评估,必须插入普通引号,结果为,',
。
怎么看
(let ((tmp (gensym)))
``(lambda (,tmp ,,tmp ,',tmp) ()))
评估为
`(LAMBDA (,TMP ,#:G42 #:G42) nil)
','X技巧用于保护X免受另一次评估。
怎么看:
(setq a 'fn)
(let ((x 'a)) ``(,,x ,',x)) ==> `(,a a) ==> (fn a)
;; ``,',X ==> `,(quote "the value of X") ==> "the value of X"
;; ``,,X ==> `,"the value of X" ==> "the value of the value of X"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.