gpt4 book ai didi

macros - Common Lisp Double-Backquote, Unquote, Quote, Unquote 序列?

转载 作者:太空宇宙 更新时间:2023-11-03 18:32:34 33 4
gpt4 key购买 nike

我正在阅读 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)

所以:

  • 不加双引号,形式已完全展开。
  • 单引号,形式不展开。
  • 未用逗号引用,表格已完全展开并引用了结果。

最佳答案

在计算双反引号形式时,首先处理内部反引号,结果是单反引号形式。在评估内部反引号形式期间,仅评估前面有两个逗号的元素。但是,评估这些双未引用元素的结果仍然(单)未引用,因此在评估结果单反引号形式时再次评估。要仅以内部反引号形式实现评估,必须插入普通引号,从而生成 ,',

看看如何

(let ((tmp (gensym)))
``(lambda (,tmp ,,tmp ,',tmp) ()))

评估为

`(LAMBDA (,TMP ,#:G42 #:G42) nil)

关于macros - Common Lisp Double-Backquote, Unquote, Quote, Unquote 序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17429521/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com