代码之家  ›  专栏  ›  技术社区  ›  asm

在macrolet上词法闭包?

  •  5
  • asm  · 技术社区  · 15 年前

    有没有一种方法可以像使用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(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 回复  |  直到 15 年前
        1
  •  5
  •   Zak    15 年前

    宏不是公共Lisp中的第一类对象,因此不能将词法闭包等效为宏。您可以通过创建一个函数来生成一个有效的lisp程序列表,然后对其进行评估,从而获得类似的效果。

    不过,这可能不是解决你问题的好办法。正如雷纳·乔斯威格所说,宏是用来操作源代码的。当你想要一个新的语法形式而不是语言内置的时候,可以使用它们。不要在可以用普通函数编写所需内容的地方使用它们。