Динамическая форма let как часть reify внутри макроса - PullRequest
2 голосов
/ 28 октября 2011

Хорошо, давайте попробуем разобраться: мое последнее намерение - предоставить пользователям макрос в виде 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

Как мне пройти этот пункт и склеить кусочки?

1 Ответ

4 голосов
/ 28 октября 2011

Кажется, что в основном ваш аргумент-вектор является ярлыком для деструктурирующей привязки:

(defscript [a b] body)  -> (reify Script (run [this {:keys [a b]}] body))

Таким образом, модель деструктурируется во время выполнения, как и должно быть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...