5

有没有办法使用宏来做类似词法闭包的事情?我想要做的是使以下宏成为本地递归助手,它在每个组合上调用一个函数,而不是像现在在 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))))))

这就是我用宏程序尝试过的并得到未定义的函数'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)))
4

1 回答 1

5

宏不是 Common Lisp 中的一等对象,因此您不能真正拥有相当于词法闭包的宏。您可以通过创建一个函数来获得类似的效果,该函数生成一个有效的 Lisp 程序列表,然后对其进行评估。

不过,这可能不是解决您问题的好方法。正如 Rainer Joswig 所说,宏用于操作源代码。当您需要一种未内置于语言中的新句法形式时,请使用它们。不要在可以用普通函数编写所需内容的地方使用它们。

于 2010-02-21T04:06:26.667 回答