По сути, я довольно плохо знаком с макросами и пытаюсь понять, как писать макросы в Clojure.Проблема в том, что я продолжаю получать ошибки исключений, и очень трудно понять, что делать дальше.Поэтому мне действительно интересно, могу ли я получить список методов (или эвристик) для отладки макросов Clojure.
Возьмите текущую проблему, над которой я работаю, у меня есть эта модель:
{:users [:name :email :registered-on]
:post [:title :author]}
и я хочу преобразовать его в форму:
(do (def new-form-users (cashew.core/new-form "/users/new" "Create a new Users"
["name" "email" "registered-on"] ("Name" "Email" "Registered-on")))
(def new-form-post (cashew.core/new-form "/post/new" "Create a new Post"
["title" "author"] ("Title" "Author"))))
, для которой я написал этот макрос:
(defmacro gen-create-forms [model]
`(do
~@(for [[entity-kw values] model]
(let [entity-sym (-> entity-kw name capitalize)
fields (vec (map name values))]
`(def ~(symbol (str "new-form-" (name entity-kw))) (new-form ~(str "/" (name entity-kw) "/new") ~(str "Create a new " entity-sym) ~fields ~(map capitalize fields)))))))
Однако, когда я запускаю макрос, я получаю:
java.lang.String cannot be cast to clojure.lang.IFn
[Thrown class java.lang.ClassCastException]
Я пытался вызвать macroexpand-1, но я получаю ту же ошибку, из-за которой у меня остается мало идей о том, как ее решить.
Это руководство, предоставленное Джоном Лоуренсом Аспденом , где он говорит: «Когда компилятор видит макрос, который является просто функцией, возвращающей некоторый код, он запускает функцию и заменяет код, которыйвозвращается в программу. "побудил меня написать макрос как функцию, которая принимает значения, которые у меня есть, и выводит результат, в который я хочу их преобразовать.
Таким образом, это работает:
(defn gen-create-forms [model]
`(do
~@(for [[entity-kw values] model]
(let [entity-sym (-> entity-kw name capitalize)
fields (vec (map name values))]
`(def ~(symbol (str "new-form-" (name entity-kw))) (new-form ~(str "/" (name entity-kw) "/new") ~(str "Create a new " entity-sym) ~fields ~(map capitalize fields)))))))
(gen-create-forms {:users [:name :email :registered-on]
:post [:title :author]})
(do (def new-form-users (cashew.core/new-form "/users/new" "Create a new Users" ["name" "email" "registered-on"] ("Name" "Email" "Registered-on"))) (def new-form-post (cashew.core/new-form "/post/new" "Create a new Post" ["title" "author"] ("Title" "Author"))))
Я не уверен, правильно ли я здесь использую макросы или же макросы являются правильной стратегией для решения этой проблемы. Однако некоторые идеи о том, что вы делаете, сталкиваясь с исключениями при написании макросов, или о хороших методах их отладки, могут бытьочень признателен.
РЕДАКТИРОВАТЬ: Mikera привлекла мое внимание, что это не хороший пример, однако мой вопрос остается в силе.Итак, чтобы повторить , какие методы вы бы использовали, если бы столкнулись с исключением, если кодирование макросов в clojure?