2017-03-03 49 views
0

我嘗試下面的代碼(瞭解宏):Clojure的模板可變參數宏

(require '[clojure.template :as temp]) 

(defn fna [x] (println "a" x) x) 
(defn fnb [x] (println "b" x) x) 

(temp/apply-template '[& fns] 
        '(fn [payload] (-> payload fns)) 
        '[fna fnb]) 
;; returns (fn [payload] (-> payload fnb)) 

我被輸出驚訝,因爲我期待:

(fn [payload] (-> payload fna fnb)) 

爲什麼產生這個輸出,以及實現上述目標的方法是什麼?我在文檔中特別提到:

argv是一個參數列表,如在defn中。

注:它可以寫成像這樣,但我想了解如何使用模板:

(defmacro wrap-fn-> [& fns] 
    `(fn [~'x#] 
    (-> ~'x 
     [email protected]))) 
+0

我會說,如果您正在學習使用'template',因爲您希望它會有用,請不要打擾。除了clojure.test之外,它並不在現實生活中使用,它是一個相當有限的工具;知道如何自己編寫宏將爲您提供更好的服務。 – amalloy

回答

1

在這裏的例子

不顯示使用「休息參數」,如[& fns]。我認爲那是你出錯的地方。試試這個:

(println 
    (temp/apply-template 
    '[x y] 
    '(fn [payload] (-> payload x y)) 
    '[fna fnb])) 

=> (fn [payload] (-> payload fna fnb)) 

順便說一句,我從來沒有見過clojure.template在使用之前 - 它看起來像一個非常專業的工具。

+0

是的,它會這樣工作,但對於固定數量的'fns',我試圖讓它帶來可變數量的參數。 請注意,這是用於學習目的(在clojure.test源文件中查看之前從未看到它)。實際上,我會使用'defmacro'來獲取可變數量的參數,並將其傳遞給'apply-template'。這是純粹的好奇心(到目前爲止)。此外,我不明白爲什麼需要'fnb'而不是'fna'。 – nha

+0

因爲'[&fns]'是包含兩個符號'&'和'fns'的參數列表,所以它「需要」'fnb'。你的模板定義忽略了第一個參數,名爲'&'並且傳遞了'fna',並且只使用了第二個參數,名爲'fns'並且傳遞了'fnb'。 – amalloy