这是我写的两个宏
(defmacro hello [x] '(+ 1 2))
&安培;
(defmacro hello [x] (eval '(+ 1 2)))
在宏扩展第一个时,我得到(+ 1 2)
,而宏扩展第二个,我得到值3.这是否意味着在编译时添加了?这怎么可能呢?如果不是'(+ 1 2)
我编写了一个查询数据库的函数,该怎么办?它会在编译时查询db吗?
答案 0 :(得分:7)
宏将任意代码注入编译器。通常,目的是"预处理"像(1 + 2)
这样的自定义代码包含在Clojure理解的内容中,如(+ 1 2)
。但是,如果您真的想要,可以将 任何 (包括数据库访问)包括在编译阶段。毕竟编译器只是在通用计算机上运行的一个软件。由于它是开源的,您可以直接修改编译器代码来执行任何操作。
使用宏只是修改/扩展基本编译器代码的一种更方便的方法,它是为扩展核心Clojure语言而优化的。但是,宏不仅限于那个用例(如果你真的想变得疯狂)。
使用C ++表达式模板机制有类似的能力,它是图灵完整的编译器预处理器。一个着名的例子是使用编译器计算前几个素数作为"错误"消息。见http://aszt.inf.elte.hu/~gsd/halado_cpp/ch06s04.html#Static-metaprogramming
答案 1 :(得分:2)
宏体在编译期间执行,其返回值用于替换代码中的用法,这个新代码将被编译。
因此你的宏代码:
(defmacro hello [x] (eval '(+ 1 2)))
实际上将以eval
形式执行'(+ 1 2)
,并且该表达式的结果值(3
)将作为宏替换其用法的结果返回(例如{ {1}})。