clojure如何在编译时评估代码?

Fai*_*lde 0 macros clojure

这是我写的两个宏

(defmacro hello [x] '(+ 1 2))

&

(defmacro hello [x] (eval '(+ 1 2)))

在宏扩展第一个,我得到(+ 1 2),而宏扩展第二个,我得到值3.这是否意味着添加发生在编译时?这怎么可能呢?如果不是'(+ 1 2)我编写了一个查询数据库的函数,该怎么办?它会在编译时查询db吗?

Ala*_*son 7

宏将任意代码注入编译器.通常,目的是"预处理"自定义代码,就像(1 + 2)Clojure所理解的那样(+ 1 2).但是,如果您真的想要,可以在编译阶段包含任何内容(包括数据库访问).毕竟编译器只是在通用计算机上运行的一个软件.由于它是开源的,您可以直接修改编译器代码来执行任何操作.

使用宏只是修改/扩展基本编译器代码的一种更方便的方法,它是为扩展核心Clojure语言而优化的.但是,宏不仅限于那个用例(如果你真的想变得疯狂).


使用C++表达式模板机制有类似的能力,它是Turing Complete编译器预处理器.一个着名的例子是使用编译器将前几个素数计算为"错误"消息.见http://aszt.inf.elte.hu/~gsd/halado_cpp/ch06s04.html#Static-metaprogramming