2016-01-21 43 views
1

我正在使用Clojure庫來嘗試向我的應用程序中的任何函數添加行爲。robert.hooke;或如何將元數據附加到Clojure中的函數

這裏就是我想要做:

(require '[robert.hooke :as hook]) 

(defn new-behavior 
    [f & args] 
    (let [id "test"] 
    (println "The new behavior is to output the ID defined at the hook level: " id) 
    (apply f args))) 

(defn add-behavior! 
    [id task-var] 
    (hook/add-hook task-var new-behavior)) 

然後我想補充一個行爲是這樣的:

(defn foo [] (println "foo test")) 

(add-behavior! "foo-id" #'foo) 

我想做些什麼能在這裏做的就是以某種方式改變在add-behavior!函數中的vartask-var函數的元數據,然後從new-behavior函數訪問新的元數據。我希望能夠做這樣的事情(注意,這不是明顯的工作):

(defn new-behavior 
    [f & args] 
    (let [id (::behavior-id (meta f))] 
    (println "The new behavior is to output the ID defined at the hook level: " id) 
    (apply f args))) 

(defn add-behavior! 
    [id task-var] 
    (alter-meta! task-var assoc-in [::behavior-id] id) 
    (hook/add-hook task-var new-behavior)) 

(defn foo [] (println "foo test")) 

(add-behavior! "foo-id" #'foo) 

目前的方法是不行的,因爲在add-behavior!它改變了var什麼的元數據我我正在訪問的new-behavior是函數的元數據,它是nil

所以,這導致了兩個問題:

  1. 我怎麼能訪問關聯到new-behaviorfunctionvar的元數據?
  2. 或者,我如何更改add-behavior中的varfunction的元數據?

回答

0

通過partial向var new-behavior提供var是否可以接受?

(defn new-behavior 
    [the-var f & args] 
    (let [id (::behavior-id (meta the-var))] 
    (println "The new behavior is to output the ID defined at the hook level: " id) 
    (apply f args))) 

(defn add-behavior! 
    [id task-var] 
    (alter-meta! task-var assoc-in [::behavior-id] id) 
    (hook/add-hook task-var (partial new-behavior task-var))) 

(defn foo [] (println "foo test")) 

(add-behavior! "foo-id" #'foo) 

不知道更多關於您試圖解決的問題,很難判斷這裏是否有更好的設計。

+0

奇妙的是,這是可行的,因爲參數約定只在'add-behavior!'和'new-behavior'之間。所以我一定會測試這個選項。我不知道「partial」,所以它是我工具箱中的一個新工具。這個想法是能夠在我的應用程序中進行配置文件,內省,日誌等任何功能,而無需更改代碼的功能。所以這樣的鉤子是完美的,一旦你可以大膽他們:) – Neoasimov

+0

完全按照預期工作。謝謝! – Neoasimov

+0

順便說一句,您可以通過匿名函數獲得與「partial」相同的功能:'#(apply new-behavior task-var%&)' – gfredericks