繁体   English   中英

Common Lisp Double-Backquote,Unquote,Quote,Unquote sequence?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM