2014-02-28 65 views
2

設置調試功能,我有這樣一個命名空間:在命令行用Clojure

(ns foo.core) 

(def ^:dynamic *debug-fn* 
    "A function taking arguments [bar baz]" 
    nil) 

(defn bar-info 
    [bar _] 
    (println bar)) 

(defn baz-info 
    [_ baz] 
    (println baz)) 

(defn do-stuff 
    [bar baz] 
    (when *debug-fn* (*debug-fn* bar baz))) 

(defn -main 
    [& {:keys [debug-fn]}] 
    (binding [*debug-fn* (symbol debug-fn)] ;; THIS WON'T WORK! 
    (do-stuff 27 42))) 

我想什麼做的是允許從這樣的命令行中指定的調試功能:lein run bar-infolein run baz-info

我不確定如何將指定的字符串作爲命令行參數,並將其轉換爲要綁定的命名空間限定函數。我需要一個宏來做到這一點嗎?

回答

6

使用ns-resolve,你將需要指定您的函數定義雖然命名空間。

user=> (defn f [n] (* n n n)) 
#'user/f 
user=> ((ns-resolve *ns* (symbol "f")) 10) 
1000 
+0

完美,謝謝! –

2

使用alter-var-root

user=> (doc alter-var-root) 
------------------------- 
clojure.core/alter-var-root 
([v f & args]) 
    Atomically alters the root binding of var v by applying f to its 
    current value plus any args 
nil 
user=> (alter-var-root #'*debug-fn* (fn [v] (fn [x] (println x) x))) 
#<user$eval171$fn__172$fn__173 [email protected]> 
user=> (*debug-fn* 1) 
1 
1 
+0

我認爲問題不在於結合,但與字符串翻譯,以調用函數 –

+0

噢,是的,我現在看到了。對不起:) –

+0

那麼,綁定也有問題,因爲我真正的'do-stuff'函數創建了一個帶有一些回調的Swing面板,因此通過'binding'擊敗了我的好意。非常感謝! –

0

雖然我已經接受了Guillermo's answer above,我想這也可能是有益的補充,我結束了去瞭解決方案:

(def debug-fns 
    {:bar-info (fn [bar _] (println bar)) 
    :baz-info (fn [_ baz] (println baz)) 

(def active-debug-fns (atom [])) 

(defn activate-debug-fn! 
    [fn-key] 
    (let [f (debug-fns fn-key)] 
    (if f 
     (swap! active-debug-fns conj f) 
     (warn (str "Debug function " fn-key " not found! Available functions are: " 
       (join " " (map name (keys debug-fns)))))))) 

(defn debug-fn-keys 
    [args] 
    (if (args "--debug") 
    (split (or (args "--debug") "") #",") 
    [])) 

(defn do-stuff 
    [bar baz] 
    (doseq [f @active-debug-fns] 
    (f bar baz))) 

(defn -main 
    [& args] 
    (let [args (apply hash-map args)] 
    (doseq [f (debug-fn-keys args)] 
     (activate-debug-fn! (keyword k))) 
    (do-stuff 27 42))) 

所以現在你可以這樣說lein run --debug bar-info來獲取信息在酒吧或lein run --debug bar,baz獲得信息在酒吧和bazes。

任何建議,以使這更習慣將愉快地接受了,並編輯了。:)