common-lisp - 为什么这个 with-gensyms 的实现会产生一个额外的逗号?
问题描述
下面的 with-gensyms 实现,旨在对类似 let 的参数列表进行操作,在嵌套的 let 中生成一个额外的逗号:
(defmacro with-gensyms (vars &rest forms)
`(let ,(loop for var in vars
collect (if (listp var)
`(,(car var) (gensym))
`(,var (gensym))))
`(let ,,(loop for genvar in vars
collect (if (listp genvar)
`(,(car genvar) ,(car (cdr genvar)))
`(,genvar nil)))
,,@forms)))
一个示例宏扩展:
(with-gensyms ((var1 1) (var2 2) (testvar "testname") the-number-zero))
(LET ((VAR1 (GENSYM))
(VAR2 (GENSYM))
(TESTVAR (GENSYM))
(THE-NUMBER-ZERO (GENSYM)))
`(LET ,((VAR1 1) (VAR2 2) (TESTVAR "testname") (THE-NUMBER-ZERO NIL))))
在嵌套的 let 的参数列表之前有一个额外的逗号,我不清楚为什么会这样。
目标输出如下:
(let ((var1 (gensym)) (var2 (gensym)) (testvar (gensym)) (the-number-zero (gensym)))
`(let ((,var1 1) (,var2 2) (,testvar "testname") (,the-number-zero nil))))
你能帮忙的话,我会很高兴!
解决方案
这值得更好的解释,而不仅仅是一个注释。有些人可能会对此感到困惑。您必须跟踪哪些括号已打开,哪些已关闭。将任何不在同一行的括号对排列起来,这样更容易解释。
(defmacro with-gensyms (vars &rest forms)
;; v-- this backticked-parenthesis has been opened here.
`(let ,(loop for var in vars
collect (if (listp var)
`(,(car var) (gensym))
`(,var (gensym))
)
)
;; ^-- but it hasn't been closed yet.
;; so we now have to unquote for that one...
;; v-- as well as this new one.
`(let ,,(loop for genvar in vars
collect (if (listp genvar)
`(,(car genvar) ,(car (cdr genvar)))
`(,genvar nil)
)
)
,,@forms
) ;; second backtick closes here.
) ;; first backtick closes here.
)
推荐阅读
- loops - Dart how to call the same function when it ends*?
- jenkins - Jenkins JCasC 将所有项目定义为代码
- python - 如何在 Airflow 中使用 Python 将 JSON 格式的数据加载到 BigQuery 表
- google-bigquery - 有没有办法在 BigQuery 中获取每个表大小的历史记录
- c# - Windows 窗体。在面板边框上绘制控件
- java - 连接到 spring AspectJ 项目时的工作流程
- python - 为什么我需要在 Django 中使用 SlugField?
- python - Docker接受python脚本的输入
- python - FOR 循环 - 按列表中的第一个元素排序
- android - Android:不允许使用 Retrofit2 调用垃圾邮件请求