2014-12-05 3 views
0

Я копирую эту функцию Java в Clojure.Что такое идиоматический способ выполнения этой функции Java в Clojure?

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

+0

Макрос определенно переполнен, если вы делаете это один раз. Но если вы делаете это много раз, это может быть полезно. –

Смежные вопросы