2012-03-22 53 views
1

我想写一个宏,写一堆宏的Lisp宏,但我有问题生成宏代码,使用splice运算符(在建立绑定),扩展内部表达式第一。编写一个Lisp宏与嵌套quasiquoting

(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

您应该更完整地显示您的代码。也就是说,包括你所有的宏的辅助函数,比如'do-list-name'等。 – Kaz 2012-03-22 05:21:55

+0

do-list-name将是'define-term-construct'生成的宏。我只想知道如何在嵌套quasiquotting中输出拼接操作符。 – 2012-03-22 05:44:30

+0

'输出符号'就像'(intern(格式无))'我接受它。 – Kaz 2012-03-22 07:21:25

回答

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,它会在define-term-construct宏的作用域中查找el变量,但不存在这种情况。

+0

这是有道理的,它现在起作用。谢谢! – 2012-03-22 18:16:42