使宏和功能更加无缝集成

mik*_*era 6 lisp compiler-construction macros functional-programming clojure

好的,我很清楚如何使用函数和宏.

我很好奇的是为什么编译器在集成两者时不能更聪明一些,例如考虑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
Run Code Online (Sandbox Code Playgroud)

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

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

Rai*_*wig 11

答案不是关于Clojure,而是一般的Lisp和宏.

记得:

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

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

现在:

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

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

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

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

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