2013-10-19 62 views
2

我有一個包含一些表單的文件,例如Clojure宏從文件「插入」代碼

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

我希望在運行時將其「插入」另一個Clojure代碼文件。

大概我可以用宏來做到這一點。我試過編寫一個讀取文件的宏,並在字符串上調用load-string,但這會導致表單在宏中被直接評估。

即上面給出的文件,我想

(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) 

回答

3

爲什麼你要在這些功能帶來的點不能用一個簡單的(利用「命名空間)?

無論如何,這裏是我認爲做的伎倆代碼:

(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 [email protected]))) 
4

你可以做到這一點與內置load功能:

;; assuming foo.clj is on the classpath 
(load "foo") 

的Clojure本身這個分裂clojure.core到幾個文件中,請參閱1.5.1版本的源代碼中緊隨this one之後的行。還請注意以這種方式加載的文件頂部的(in-ns 'clojure.core)

當然,使用宏更靈活,因爲它允許您在任意位置注入代碼,以任意方式對其進行轉換等。但是,如果您只想分割多個文件之間的名稱空間,則load會更簡單。