Macros 公共Lisp双反引号,反引号,引号,反引号序列?
我正在阅读《让我超越Lambda》,它涉及一些非常深层次的宏创作。这很吸引人,我主要是设法跟上它 在第4章中,Hoyte为CL-PPCRE匹配和替换函数实现了读卡器宏,以便您可以执行以下操作:Macros 公共Lisp双反引号,反引号,引号,反引号序列?,macros,lisp,common-lisp,Macros,Lisp,Common Lisp,我正在阅读《让我超越Lambda》,它涉及一些非常深层次的宏创作。这很吸引人,我主要是设法跟上它 在第4章中,Hoyte为CL-PPCRE匹配和替换函数实现了读卡器宏,以便您可以执行以下操作: (#~m/(foo|bar)\d+/ "Some foo99") ; matches! (#~s/foo(\d+)/bar\1/, "Some foo99") ; "Some bar99 为了实现这一点,我们定义了一个使用双反引号的宏,因为它实际上是由包装器宏展开的,包装器宏需要带引号的值(它返回
(#~m/(foo|bar)\d+/ "Some foo99") ; matches!
(#~s/foo(\d+)/bar\1/, "Some foo99") ; "Some bar99
为了实现这一点,我们定义了一个使用双反引号的宏,因为它实际上是由包装器宏展开的,包装器宏需要带引号的值(它返回lambda形式)。在准引号列表中,使用了以下序列,',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"
您最后的defmacro引用了
str
。这是怎么一回事?它的定义是什么?你能演示一下如何调用pcre/match lambda form
吗?啊,这需要一些解释,因为实际上有很多层宏在进行。这本书是推动宏创作的边界(为了乐趣和教育)str
是一个由一个封闭的LET
定义的符号,它表示一个可以安全使用的变量名。pcre/match lambda form
这样叫:(pcre/match lambda form'(“foo”)
,其中“foo”
已经被处理#~m/foo/
格式字符串的流读取器读取。我正在以打印格式读取它,但它(部分)也可以在线获取:这里没有对错。根据:如果替代形式F2的副作用行为也与上述描述一致,则实现可以自由地将后引形式F1解释为任何形式F2,在评估时,将产生与上述定义所暗示的结果相同或相等的结果。也就是说,在进行任何比较之前,必须对表格进行全面评估。哇,这有点复杂。我现在只是在玩一些基本的双反引号和那些不同的反引号,看看在每种情况下会发生什么。我现在明白了,谢谢:)@d11wtq您可能还想看看“Common Lisp the Language”的附录C(backquote),该附录包含一个示例实现和backquote语法示例。