Начните с просмотра этого ответа о макросах . Затем медленно наращивайте его.
Не то, что, поскольку db
всегда используется только внутри вашей сконструированной функции, он не обязательно должен быть параметром для вызова макроса.
Первая итерация:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(defn db-event-impl
[[name params]]
(spyx name)
(spyx params)
(let [result `(re-frame.core/reg-event-db
)
]
(spyx-pretty result))
)
(dotest
(db-event-impl (quote [:some-name [foo bar]]))
)
с результатом:
name => :some-name
params => [foo bar]
result =>
(re-frame.core/reg-event-db)
добавьте еще код:
(defn db-event-impl
[[name params]]
(spyx name)
(spyx params)
(let [result `(re-frame.core/reg-event-db
~name
(fn [~'db ; trick to prevent namespacing of `db`
~params ]
(assoc ~'db )
) ) ]
(spyx-pretty result)) )
и получите:
name => :some-name
params => [foo bar]
result =>
(re-frame.core/reg-event-db
:some-name
(clojure.core/fn [db [foo bar]] (clojure.core/assoc db)))
Добавьте еще для assoc
часть:
(let [assoc-form (->list
(apply glue
(quote [assoc db])
(forv [param params]
[(->kw param) param])))
result `(re-frame.core/reg-event-db
~name
(fn [~'db ; trick to prevent namespacing of `db`
~params]
(assoc ~'db)
))]
(spyx assoc-form)
(spyx-pretty result)))
с результатом:
name => :some-name
params => [foo bar]
assoc-form => (assoc db :foo foo :bar bar)
result =>
(re-frame.core/reg-event-db
:some-name
(clojure.core/fn [db [foo bar]] (clojure.core/assoc db)))
Затем сложите все вместе:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(defn db-event-impl
[[name params]]
(let [assoc-form (->list
(apply glue
(quote [assoc db])
(forv [param params]
[(->kw param) param])))
result `(re-frame.core/reg-event-db
~name
(fn [~'db ; trick to prevent namespacing of `db`
~params]
~assoc-form))]
result))
(defmacro db-event
[& args]
(db-event-impl args))
(dotest
(let [expected (quote
(re-frame.core/reg-event-db
:some-name
(clojure.core/fn [db [foo bar]]
(assoc db :foo foo :bar bar))))]
(is= expected
(db-event-impl (quote [:some-name [foo bar]])))))