2014-02-28 25 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。

任何建议,以使这更习惯将愉快地接受了,并编辑了。:)