关于macrolet的词法封闭?

时间:2010-02-20 02:12:33

标签: lisp common-lisp lexical-closures

有没有办法使用macrolet进行词法闭包?我想要做的是使下面的宏成为一个局部递归助手,它调用每个组合上的函数而不是生成列表,因为它现在调用repl中的宏导致:

CL-USER> (combinations nil '(1 2 3) '(4 5 6))
((1 4) (1 5) (1 6) (2 4) (2 5) (2 6) (3 4) (3 5) (3 6))

我想要的是一个宏,它接受一个函数和任意数量的列表,并导致嵌套循环调用每个组合上的函数。我是lisp的新手,这是我在'nif'克隆之外编写的第一个宏,所以任何建议都值得赞赏。

我试图将宏转换为宏中的一个宏,它接受一个函数并将'(nreverse(list,item,@ vars))'替换为''(func(nreverse(list,item, @vars)))'但是我得到的错误是func是一个未定义的变量或函数。

这是原始功能:

(defmacro combinations (vars &rest lsts)
  (with-gensyms (item)
    `(loop for ,item in ,(car lsts) ,(if (null (cdr lsts)) 'collecting 'nconcing)
       ,(if (null (cdr lsts))
            `(nreverse (list ,item ,@vars))
            `(combinations (,item ,@vars) ,@(cdr lsts))))))

这是我尝试使用macrolet并获得未定义的函数'func'错误。

(defmacro for-all-combonations (func &rest lst)
       (macrolet ((for-all (vars &rest lsts)
                    (with-gensyms (item)
                      `(loop for ,item in ,(car lsts) ,(if (null (cdr lsts)) 
                                                           'collecting 'nconcing)
                            ,(if (null (cdr lsts))
                                 `(func (nreverse (list ,item ,@vars)))
                                 `(for-all (,item ,@vars) ,@(cdr lsts)))))))
         (for-all nil lst)))

1 个答案:

答案 0 :(得分:5)

宏不是Common Lisp中的第一类对象,因此你不能真正拥有等效的词法闭包作为宏。您可以通过创建一个生成列表的函数来获得类似的效果,该列表是一个有效的Lisp程序,然后逐出它。

虽然这对你的问题可能不是一个很好的解决方案。正如Rainer Joswig所说,宏用于操纵源代码。当您需要一种未内置于该语言的新语法形式时,请使用它们。不要在可以用普通功能写出你想要的东西的地方使用它们。