我正在阅读 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
,我无法理解。最初的作用是什么,'
在这里做吗?
(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)
So:
- 双引号不加引号,形式已完全展开。
- 单引号,形式不扩展。
- 不使用逗号引用,形式完全展开并引用结果。