有没有办法使用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)))
答案 0 :(得分:5)
宏不是Common Lisp中的第一类对象,因此你不能真正拥有等效的词法闭包作为宏。您可以通过创建一个生成列表的函数来获得类似的效果,该列表是一个有效的Lisp程序,然后逐出它。
虽然这对你的问题可能不是一个很好的解决方案。正如Rainer Joswig所说,宏用于操纵源代码。当您需要一种未内置于该语言的新语法形式时,请使用它们。不要在可以用普通功能写出你想要的东西的地方使用它们。