2010-02-20 70 views
5

有没有一种方法可以像使用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并获得未定义功能“功能”的错误。

(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))) 
+2

你能解释一下为什么你想使用这个宏吗?什么应该(让((a'((1 2 3)(4 5 6))))(组合无))? – 2010-02-20 04:23:43

+0

它应该返回'(((1 2 3))(((4 5 6))),它是每个组合的每个输入列表中取一个元素的所有组合的列表。我正在用宏来做这件事,因为这正是我现在正在探索的。我可以在没有宏的情况下做到这一点,但我想试着写一个比nif复杂的宏。这让我有机会找出可以做什么和不可以做什么,我永远不会想知道是否可以用这种方式来使用小应用程序。希望一旦我完成这个,我会理解更好的宏。 – asm 2010-02-20 18:42:00

+2

我不认为这与宏有关。宏可以用来计算源代码,而不是数据。如果你想计算数据,数据需要在宏扩展时间 - 通常不是。 – 2010-02-20 23:37:34

回答

5

宏不是Common Lisp中的第一类对象,所以你不可能真正具有与宏一样的词法闭包。你可以通过创建一个生成一个有效的Lisp程序列表的函数来获得相似的效果,然后对其进行处理。

虽然这可能不是一个很好的解决方案。正如Rainer Joswig所说,宏是用来操纵源代码的。当你想要一种不属于该语言的新语法形式时使用它们。不要在可以用普通函数写你想要的东西的地方使用它们。

+0

好吧,你说服了我。我想这是这次探索的结束。 – asm 2010-02-22 02:16:50

+0

@Andrew Myers - 对于一流宏的想法已经有了一些探索。最近我读到的是Paul Graham考虑Arc的想法。我认为他最终放弃了它,因为它使得编译器对于不确定的好处更加复杂。 – Zak 2010-03-08 06:01:38