Compiler construction 使宏和函数更无缝地集成

Compiler construction 使宏和函数更无缝地集成,compiler-construction,functional-programming,macros,clojure,lisp,Compiler Construction,Functional Programming,Macros,Clojure,Lisp,好的,我非常了解如何使用函数和宏 我很好奇为什么编译器在整合这两个编译器时不能更聪明一点,例如考虑Culjule:< /P> (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”来实现这一点,但是为什么编译器自己不能弄清楚如何实现这一点呢

好的,我非常了解如何使用函数和宏

我很好奇为什么编译器在整合这两个编译器时不能更聪明一点,例如考虑Culjule:< /P>
(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/other Lisp中,是否可以创建一个版本的apply或其他更高阶函数,使函数和宏作为参数都能很好地工作?

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

记住:

APPLY是为了能够使用在运行时创建的参数列表调用函数

宏用于从某些源代码生成新的源代码,生成的源代码将运行

现在:

如果允许apply在运行时将不同的源代码馈送到宏中,则需要能够在运行时生成结果代码并执行生成的代码

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

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

在基于解释程序的Lisp中,可能会有更多的信息,并且可以始终应用宏


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

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