Как исправить этот макрос? - PullRequest
0 голосов
/ 08 мая 2020

Я пытаюсь преобразовать свой макрос в следующее расширение:

(re-frame.core/reg-event-db
 :some-name
 (fn [db [foo bar]]
   (assoc db :foo foo :bar bar)
   ))

, и у меня это пока есть

(defmacro db-event 
  [name params & body]
  `(re-frame.core/reg-event-db
    ~name
    (fn [db ~params]
      ~@body)))

Но это действительно не работает, когда я пытаюсь с

(db-event :some-name [foo bar] 
  (assoc db :foo foo :bar bar))

я получаю следующее:

------ WARNING - :undeclared-var -----------------------------------------------
 Resource: :1:17
 Use of undeclared Var vendo.macros/foo
--------------------------------------------------------------------------------
------ WARNING - :undeclared-var -----------------------------------------------
 Resource: :1:21
 Use of undeclared Var vendo.macros/bar
--------------------------------------------------------------------------------
------ WARNING - :undeclared-var -----------------------------------------------
 Resource: :1:33
 Use of undeclared Var vendo.macros/db
--------------------------------------------------------------------------------
------ WARNING - :undeclared-var -----------------------------------------------
 Resource: :1:41
 Use of undeclared Var vendo.macros/foo
--------------------------------------------------------------------------------
------ WARNING - :undeclared-var -----------------------------------------------
 Resource: :1:50
 Use of undeclared Var vendo.macros/bar
--------------------------------------------------------------------------------


(re-frame.core/reg-event-db {:foo nil, :bar nil} (cljs.core/fn [vendo.macros/my-db nil]))

Как мне это исправить?

1 Ответ

0 голосов
/ 09 мая 2020

Начните с просмотра этого ответа о макросах . Затем медленно наращивайте его.

Не то, что, поскольку 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]])))))
...