Хорошо, давайте попробуем разобраться: моя конечная цель — предоставить пользователям макрос в виде API, который будет выглядеть так:
(defscript [a b]
(println a))
Результатом должен быть экземпляр протокола Script
, который выглядит так:
(defprotocol Script
(run [this model]))
Идея состоит в том, что первый аргумент defscript
— это список символов, которые необходимо связать с соответствующими ключами в model
:
(.run (defscript [a b] (println a)) {:a 1}) ;; yields 1
Я не могу придумать никакого кода, который мог бы эффективно производить такой эффект, так как я постоянно натыкаюсь на стену, пытаясь использовать параметр model
, так как во время раскрытия макроса это просто символ:
(defmacro invoke-
[params model body]
(let [p (flatten (map (fn [x] [x (model (keyword x))]) params))]
`(let [~@p]
~body)))
(defmacro defscript
[params & body]
`(reify Script
(run [~'this ~'model]
(invoke- ~params ~'model ~@body))))
invoke-
отлично работает, если вызывается напрямую:
(invoke- [a] {:a 1} (println a)) ;; prints 1
но это не работает при использовании в defscript
, так как model
не может быть правильно расширено:
(.run (defscript [a] (println a)) {:a 1}) ;; prints nil
Как я могу обойти этот момент и склеить кусочки вместе?
clojure.template
. - person Alex Taggart   schedule 28.10.2011