2012-08-02 23 views
3

我有這個函數,它在xml結構中給我一個父節點的id。作爲關鍵字展開多個參數

(ns foo.core 
    (:require [clojure.data.zip.xml :as cdzx])) 

(defn id-of-parent [zipper child-id node1 node2 node3 node4] 
    (cdzx/xml-> zipper node1 node2 node3 node4 
    (cdzx/attr= :Id child-id) zip/up zip/up (cdzx/attr :Id))) 

它會被稱爲像

(id-of-parent zipper child-id :Foos :Foo :Bars :Bar) 

我現在想使這個功能比較一般通過一個簡單的「&路徑」取代四「節點」這樣我就可以使用任意數量的節點來設置路徑。

(defn id-of-parent [zipper child-id & path] 
    (cdzx/xml-> zipper ????path???? 
    (cdzx/attr= :Id child-id) zip/up zip/up (cdzx/attr :Id))) 

將關鍵字序列展開爲單個關鍵字的正確方法是什麼?

回答

4

unquote-splicing feature of the syntax-quote函數幾乎總是用於在宏中構建函數調用,儘管它恰好適合於構建函數調用。

(defn id-of-parent [zipper child-id & path] 
     (apply cdzx/xml-> `(~zipper [email protected] 
      ~(cdzx/attr= :Id child-id) ~zip/up ~zip/up ~(cdzx/attr :Id)))) 

因爲xml->是一個函數,而不是你可以使用應用

+0

這種方法是行不通的。例如。不會評估對'attr ='或'zip/up'的調用。所以你得到一個列表或符號而不是謂詞。 – kotarak 2012-08-03 06:19:41

+0

忘記了其他人,修好了 – 2012-08-03 19:01:22

+0

修復了拉鍊未找到引用。 – kotarak 2012-08-03 19:27:54

1

您可以使用apply構建調用它的宏。

(defn id-of-parent 
    [zipper child-id & path] 
    (->> [(cdzx/attr= :Id child-id) zip/up zip/up (cdzx/attr :Id)] 
    (concat path) 
    (apply cdzx/xml-> zipper))) 
1

應用可以使用,如:

(defn id-of-parent 
    [zipper child-id & path] 
    (let [pred [path (cdzx/attr= :Id child-id) zip/up zip/up (cdzx/attr :Id)]] 
    (apply cdzx/xml-> zipper (flatten pred)))) 
+1

這給了我一個ClassCastException clojure.lang.Keyword無法轉換爲clojure.lang.IObj clojure.core/with-meta(core.clj:211) – mmoehring 2012-08-04 17:20:38

相關問題