使宏和功能更加无缝集成

时间:2010-07-02 11:52:06

标签: compiler-construction functional-programming macros clojure lisp

好的,我很清楚如何同时使用函数和宏。

我很好奇的是,为什么编译器在集成两者时不能更聪明一些,例如:考虑Clojure代码:

(defmacro wonky-add [a b] `(+ ~a (* 2 ~b)))

(defn wonky-increment [a] (apply wonky-add a 1))
=> Error: can't take value of a macro

是的,我知道我可以通过取出“apply”来完成这项工作 - 但为什么编译器无法弄清楚如何自己做这个呢?

在Clojure /其他LISP中是否可以创建一个apply或其他更高阶函数的版本,这些函数同时兼容函数和宏作为参数?

2 个答案:

答案 0 :(得分:11)

这个答案不是关于Clojure,而是一般的Lisp和宏。

记住:

APPLY可以使用在运行时创建的参数列表调用函数。

宏可以从一些源代码生成新的源代码 - 生成的源代码将运行。

现在:

如果允许apply在运行时将不同的源代码提供给宏,则需要能够在运行时生成结果代码并执行生成的代码。

因此,在编译的Lisp系统中,每次使用宏调用APPLY都可能会创建需要在运行时编译的新代码,以便能够执行它。这也意味着当您的代码执行并且代码有问题时,您可能会在运行时获得新的编译器错误。因此,要在运行时应用宏,您需要一个编译器和所有必要的信息(例如其他宏)才能扩展和编译代码。

这也意味着在一般情况下你不能在运行时之前用宏编译APPLY,因为不知道要应用的运行时参数是什么。

在基于解释器的Lisp中,可能会有更多的信息和宏可以一直应用。

在早期的Lisp中,有正常的功能和所谓的FEXPR。 FEXPR允许灵活的调用和运行时代码操作。在Lisp的历史后期,它们已被宏替换,因为宏允许高效编译,并且在基于编译器的系统中,允许在运行时之前处理语法错误。

答案 1 :(得分:2)

您所描述的内容听起来像是一流的宏(即:您可以像函数一样操作的宏)。有些lisps有这些(例如Arc),但apply由于不是宏本身,可能仍然无效。