Macros Clojure宏到";插入“;文件中的代码

Macros Clojure宏到";插入“;文件中的代码,macros,clojure,Macros,Clojure,我有一个包含一些表格的文件,例如 (clojure.core/defn x [] (clojure.core/+ 5 7)) (clojure.core/defn y [a] (clojure.core/+ a 5)) 我希望在运行前被“插入”到Clojure代码的另一个文件中 大概,我可以使用宏来实现这一点。我尝试编写一个宏来读取文件并对字符串调用load string,但这会导致表单在宏中直接求值 i、 鉴于上述文件,我想 (some-other-code) ... (my-macro)

我有一个包含一些表格的文件,例如

(clojure.core/defn x [] (clojure.core/+ 5 7))
(clojure.core/defn y [a] (clojure.core/+ a 5))
我希望在运行前被“插入”到Clojure代码的另一个文件中

大概,我可以使用宏来实现这一点。我尝试编写一个宏来读取文件并对字符串调用
load string
,但这会导致表单在宏中直接求值

i、 鉴于上述文件,我想

(some-other-code) ...

(my-macro)

(some-more-other-code)
扩展到

(some-other-code) ...

(clojure.core/defn x [] (clojure.core/+ 5 7))
(clojure.core/defn y [a] (clojure.core/+ a 5))

(some-more-other-code)
为什么不在要引入这些函数的地方使用一个简单的名称空间呢

不管怎么说,下面是我认为能起作用的代码:

(defn stream []
  (java.io.PushbackReader. (clojure.java.io/reader (clojure.java.io/file "foo.clj"))))

(defmacro insert []
  (let [content (with-open [s (stream)]
                  (loop [forms-so-far []]
                    (if-let [next-form (read s false nil)]
                      (recur (conj forms-so-far next-form))
                      forms-so-far)))]
    `(do ~@content)))

您可以使用内置的
load
功能来实现这一点:

;; assuming foo.clj is on the classpath
(load "foo")
Clojure本身就是这样将
Clojure.core
拆分成几个文件的,请参见1.5.1版本的源代码中紧跟其后的几行。还要注意以这种方式加载的文件顶部的
(在ns'clojure.core中)

当然,使用宏更灵活,因为它允许您在任意位置插入代码、以任意方式转换代码等。但是,如果您只想在多个文件之间划分名称空间,则加载会更简单