はい、あなたは簡単にこのようなマクロでそれを行うことができます:
(defmacro map-to [type mappings entity]
`(doto (new ~type)
[email protected](map (fn [[field entity-field]]
`(~(symbol (str ".set" (clojure.string/capitalize field)))
(~entity-field ~entity)))
mappings)))
これはあなたが必要とする正確なコードを生成します:
(map-to java.util.Date {date :dt minutes :mm hours :h}
{:dt 10 :mm 22 :h 12})
は以下に展開されます:
(doto
(new java.util.Date)
(.setDate (:dt {:dt 10, :mm 22, :h 12}))
(.setMinutes (:mm {:dt 10, :mm 22, :h 12}))
(.setHours (:h {:dt 10, :mm 22, :h 12})))
ここにいくつか注意してください:
1)新しい変数new-obj
を導入する必要はありません。doto
は操作対象のオブジェクトを返します。
2)マッピングはリテラルマップとして渡す必要があります。それ以外の場合は、.
特殊フォームに渡すキーを取得できないためです。
3)entity
マップが繰り返されていることがわかります。REPLで
(let [entity20047 {:dt 10, :mm 22, :h 12}]
(doto
(new java.util.Date)
(.setDate (:dt entity20047))
(.setMinutes (:mm entity20047))
(.setHours (:h entity20047))))
:
user> (map-to java.util.Date {date :dt minutes :mm hours :h}
{:dt 10 :mm 22 :h 12})
;;=> #inst "2016-09-10T09:22:48.867-00:00"
user> (let [ent {:dt 10 :mm 22 :h 12}]
(map-to java.util.Date {date :dt minutes :mm hours :h} ent))
;;=> #inst "2016-09-10T09:22:48.899-00:00"
(値は3時間早いので、今ではこのように拡大し
(defmacro map-to [type mappings entity]
(let [ent (gensym "entity")]
`(let [~ent ~entity]
(doto (new ~type)
[email protected](map (fn [[field entity-field]]
`(~(symbol (str ".set" (clojure.string/capitalize field)))
(~entity-field ~ent)))
mappings)))))
:あなたは、マクロ内で結合別を導入することでこの問題を解決することができます私のタイムゾーン(gmt + 3)のために)
更新
(get-in
付き)ご希望の動作を取得するために、あなたは少しだけ、このマクロを変更することができます。REPLで
(defmacro map-to [type mappings entity]
(let [ent (gensym "entity")]
`(let [~ent ~entity]
(doto (new ~type)
[email protected](map (fn [[field entity-field]]
`(~(symbol (str ".set" (clojure.string/capitalize field)))
(get-in ~ent ~entity-field)))
mappings)))))
:
今
(let [entity20094 {:date {:dt 10}, :time {:mm 22, :h 12}}]
(doto
(new java.util.Date)
(.setDate (get-in entity20094 [:date :dt]))
(.setMinutes (get-in entity20094 [:time :mm]))
(.setHours (get-in entity20094 [:time :h]))))
:
user> (map-to java.util.Date {date [:date :dt]
minutes [:time :mm]
hours [:time :h]}
{:date {:dt 10} :time {:mm 22 :h 12}})
;;=> #inst "2016-09-10T09:22:41.935-00:00"
はに展開マッピング関数の作成を自動化するもう1つのマクロを作ることができます:
あなたはクラスオブジェクトからメーカー名を生成する機能を必要とするすべての最初:
今
(defn make-name [c]
(->> c
.getName
(#(clojure.string/split % #"\."))
(clojure.string/join "-")
(str "create-")
symbol))
user> (make-name java.util.Date)
;;=> create-java-util-Date
エンティティからインスタンスを作成するための関数を定義するマクロ:
(defmacro defmapper [type mappings]
`(defn ~(make-name type) [entity#]
(map-to ~type ~mappings entity#)))
この1つは関数を作成し、つまり、エンティティを指定すると、それをクラスインスタンスに変換します。 REPLで
(defn create-java-util-Date [entity__20122__auto__]
(map-to
java.util.Date
{date [:date :dt], minutes [:time :mm], hours [:time :h]}
entity__20122__auto__))
:
(defmapper java.util.Date {date [:date :dt]
minutes [:time :mm]
hours [:time :h]})
は、次のように拡張されますそれはちょうど通常の関数です
user> (map create-java-util-Date
[{:date {:dt 10} :time {:mm 22 :h 12}}
{:date {:dt 11} :time {:mm 22 :h 12}}
{:date {:dt 12} :time {:mm 22 :h 12}}])
;;(#inst "2016-09-10T09:22:18.974-00:00"
;; #inst "2016-09-11T09:22:18.974-00:00"
;; #inst "2016-09-12T09:22:18.974-00:00")