Учитывая экземпляр Java obj
и имя члена (строка) "Foo"
, а также карту conf
, я пытаюсь сгенерировать код Clojure, который будет выглядеть следующим образом:
(if (get conf "Foo")
(set! (.Foo obj) (get conf "foo")
obj)
А также, если я знаю, что "SomeEnum"
- это имя перечисления Java, код такой:
(if (get conf "SomeEnum")
(set! (.someEnum obj)(Enum/valueOf SomeEnum (get conf "SomeEnum")))
obj)
Вот что я придумал:
(defmacro set-java [obj conf obj-name]
`(if (get ~conf ~obj-name)
(set! (. ~obj ~(symbol obj-name)) (get ~conf ~obj-name))
~obj))
(defn lowercase-first [s]
(apply str (Character/toLowerCase (first s)) (rest s)))
(defmacro set-java-enum [obj conf obj-name]
`(if (get ~conf ~obj-name)
(set! (. ~obj ~(symbol (lowercase-first obj-name)))
(Enum/valueOf ~(symbol obj-name) (get ~conf ~obj-name)))
~obj))
Тестирование с macroexpand
, кажется, дает правильный результат, но после попытки:
(defn ^Policy map->policy [conf]
(-> (Policy.)
(set-java-enum conf "CommitLevel")
(set-java conf "durableDelete")
(set-java conf "expiration")
(set-java conf "generation")
(set-java-enum conf "GenerationPolicy")
(set-java-enum conf "RecordExistsAction")
(set-java conf "respondAllOps")))
У меня странный бесконечный цикл предупреждений об отражениях.
--- редактировать ---
после долгого времени с этим я отказался от потоков (->
) и закончил:
(defmacro set-java [obj conf obj-name]
`(when (get ~conf ~obj-name)
(set! (. ~obj ~(symbol obj-name)) (get ~conf ~obj-name))))
(defn lowercase-first [s]
(apply str (Character/toLowerCase ^Character (first s)) (rest s)))
(defmacro set-java-enum [obj conf obj-name]
`(when (get ~conf ~obj-name)
(set! (. ~obj ~(symbol (lowercase-first obj-name)))
(Enum/valueOf ~(symbol obj-name) (get ~conf ~obj-name)))))
(defn map->write-policy [conf]
(let [wp (WritePolicy. (map->policy conf))]
(set-java-enum wp conf "CommitLevel")
(set-java wp conf "durableDelete")
;; more non threaded object manipulation
wp))
Так что я до сих пор не уверен, о чем был бесконечный цикл предупреждения об отражении, но, надеюсь, это также полезно и может быть улучшено в дальнейшем.