asm*_*asm 5 lisp lexical-closures common-lisp
有没有办法使用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)))
宏不是Common Lisp中的第一类对象,因此你不能真正拥有等效的词法闭包作为宏.您可以通过创建一个生成列表的函数来获得类似的效果,该列表是一个有效的Lisp程序,然后进行验证.
尽管如此,这可能不是一个很好的解决方案.正如Rainer Joswig所说,宏用于操纵源代码.当您需要一种未内置于该语言的新语法形式时,请使用它们.不要在可以用普通功能编写所需内容的地方使用它们.