2014-12-05 59 views
0

我將這個Java函數複製到Clojure中。在Clojure中做這個Java函數的慣用方式是什麼?

Config createConfig(Map<String, String> options) { 
    Config conf = new Config(); 
    String foo = options.get("foo"); 
    if (foo != null) { conf.setFoo(foo); } 
    String bar = options.get("bar"); 
    if (bar != null) { conf.setBar(bar); } 
    // many other configs 
    return conf; 
} 

我想出了這個,

(defn create-config [options] 
    (let [conf (Config.)] 
    (when-let [a (:foo options)] (.setFoo a)) 
    (when-let [a (:bar options)] (.setBar a)) 
    conf)) 

有沒有更好的方式來做到這一點?

回答

2

這個怎麼樣?

(defn create-config [{:keys (foo bar)}] 
    (let [config (Config.)] 
    (when foo (.setFoo config foo)) 
    (when bar (.setBar config bar)))) 

可能更好的是創建一個通用宏,它可以基於Clojure地圖設置對象上的任意數量的字段。這可能是更漂亮,但它的工作原理:

(defmacro set-fields 
    [options obj] 
    (let [o (gensym) 
     m (gensym)] 
    `(let [~m ~options 
      ~o ~obj] 
     [email protected](map (fn [[field value]] 
       (let [setter (symbol (str "set" (clojure.string/capitalize (name field))))] 
        `(. ~o (~setter ~value)))) 
       options) 
     ~o))) 

;; call like: 
(set-fields {:daemon true :name "my-thread"} (Thread.)) 

;; translates to: 
;; (let [G__1275 {:daemon true, :name "my-thread"} 
;;  G__1274 (Thread.)] 
;; (. G__1274 (setDaemon true)) 
;; (. G__1274 (setName "my-thread")) 
;; G__1274) 

我沒有檢查空,因爲這只是着眼於究竟是什麼在選項中傳遞。

+0

我喜歡你的'create-config'。它對我來說很好看。由於'clojure.string/capitalize',宏對我來說有點矯枉過正。謝謝! – woodings 2014-12-05 08:16:41

+0

如果你這樣做了一次,宏是絕對矯枉過正的。但是如果你做了很多次,這可能是值得的。 – 2014-12-05 15:14:10