我试图写一个编写一堆宏的Lisp宏,但是我在生成使用splice运算符(在build-bind中)的宏代码时遇到了问题,它首先扩展了表达式。< / p>
(defmacro define-term-construct (name filter-p list-keywords)
(let* ((do-list-name (output-symbol "do-~a-list" name))
(with-name (output-symbol "with-~a" name))
(do-filter-name (output-symbol "do-~as" name)))
`(progn
(defmacro ,do-list-name
(ls (&key ,@(append list-keywords '(id operation))) &body body)
(with-gensyms (el)
`(loop-list (,el ,ls :id ,id :operation ,operation)
(let (XXX,@(build-bind ,,name ,el))
(when (,',filter-p ,el)
(,',with-name ,el
,@body)))))))))
第一遍后,我想得到:
(define-term-construct some some-p (args name))
->
(PROGN
(DEFMACRO DO-SOME-LIST (LS (&KEY ARGS NAME ID OPERATION) &BODY BODY)
(WITH-GENSYMS (EL)
`(LOOP-LIST (,EL ,LS :ID ,ID :OPERATION ,OPERATION)
(LET (,@(BUILD-BIND ,SOME ,EL))
(WHEN (SOME-P ,EL)
(WITH-SOME ,EL
,@BODY)))))))
知道我应该使用什么引用/ quasiquotes来获得所需的代码?
答案 0 :(得分:1)
您说想要获得的输出具有不平衡的逗号。 ,@
已经平衡了反引号,因此您无法拥有,SOME
和,EL
。这是两个级别的不引用/拼接内部只有一个反引用级别。
我怀疑你想要:
`(WITH-GENSYMS (EL) ... (LET (,@(BUILD-BIND 'SOME EL)) ...))
some
符号作为原始宏的参数出现,并且在传递给build-bind
函数时必须以引号结尾。 EL
是直接评估的。它只是由WITH-GENSYMS
绑定构造引入的局部变量,并且它不再处于反引号上下文中,因为它位于拼接内部。
将其转录回原始外部宏的反引号:SOME
变为,name
:
,@(build-bind ',name el) ;; two commas out balance two backquotes in
符号是保护引号下的拼接版,它将确保它被视为符号而不是变量。
el
不需要拼接;它不是可变材料,而是生成模板的硬编码功能。如果您要放置,el
,它会在el
宏的范围内查找define-term-construct
变量,其中不存在此类内容。