Макростың ішінде қайта құрудың бір бөлігі ретінде динамикалық мүмкіндік береді

Жарайды, оны түзетуге тырысайық: менің түпкілікті мақсатым макросты пайдаланушыларға арналған API ретінде ұсыну:

(defscript [a b]
  (println a))

Нәтиже сценарийі протоколының мысалы болуы керек, ол келесідей:

(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 [[email protected]]
       ~body)))

(defmacro defscript
  [params & body]
  `(reify Script
    (run [~'this ~'model]
      (invoke- ~params ~'model [email protected]))))

invoke- works fine if called directly:

(invoke- [a] {:a 1} (println a)) ;; prints 1

бірақ үлгі ретінде defscript ішінде қолданылған кезде дұрыс жұмыс істемейді:

(.run (defscript [a] (println a)) {:a 1}) ;; prints nil

Осы нүктеден қалай өтуге болады және бөліктерді біріктіре аламын?

2
Сіз сипаттайтын нәрселер clojure.template ішіндегі мүмкіндіктерге мүлдем ұқсамайды.
қосылды автор Alex Taggart, көзі

1 жауаптар

Негізінде сіздің дәлелдеріңіздің векторы бұзылуды байланыстырудың қысқалығы болып табылады:

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

Осылайша, модель жұмыс уақыты кезінде де бұзылады.

4
қосылды
Шынында өте жақсы!
қосылды автор kotarak, көзі
таза құбылыс, рахмет!
қосылды автор skuro, көзі