Ваша последняя функция, возвращенная после вызова uia
, нигде не включает контекстную карту:
>>> (macroexpand-1
'(uia {mt "dt"}
[{ et "wa" s "a1"}
{et "wa" s "a2"}
{et "um" s "a3"}]
[et1 id cid]
(block {} (prn "auto1"))))
(user/block
{mt "dt"}
(clojure.core/fn [et1 id cid]
(clojure.core/prn "got" [et1 id cid] mt)))
>>> (macroexpand-1
'(user/block
{mt "dt"}
(clojure.core/fn [et1 id cid]
(clojure.core/prn "got" [et1 id cid] mt))))
(clojure.core/let [mt "dt"]
(clojure.core/fn [et1 id cid] (
clojure.core/prn "got" [et1 id cid] mt)))
В результате получается функция, которая принимает заданное вами значение с закрытой над свободной переменной mt
привязан к «dt» - контекстную карту нигде не найти.
Я подозреваю, что ваше определение block
не соответствует вашим ожиданиям или, по крайней мере, подпись неверна.
(defmacro block [ctx & expr]
`(let [~@(mapcat (fn [[k v]] [k v]) ctx)] ~@expr))
Фактическим аргументом, который вы передаете блоку, является карта метаданных, а не карта контекста.Если это преднамеренно, я бы изменил подпись, чтобы отразить замену ctx
на mt
в подписи и теле.
Что касается того, почему он печатается только три раза, то при рассмотрении окончательного расширения выше следует сделатьclear - возвращаемое замыкание принимает 3 аргумента и просто печатает их внутри вектора вместе с метаданными (на которые ссылается закрытый символ mt
из внешнего let
.
(defmacro uia [metadata ctx arity & expr]
`(block ~metadata
(fn ~arity
(dotimes [n# ~(count ctx)]
(prn "got" ~arity ~'mt)))))
Теперь с этим изменениемкогда вы набираете uia
следующие отпечатки:
"got" ["x" 11 22] "dt"
"got" ["x" 11 22] "dt"
"got" ["x" 11 22] "dt"
Это шаг в правильном направлении, но ваш вопрос указывает, что вы также хотите, чтобы значения внутри карты печатались вместе с закрытыми метаданными и3 аргумента функции.Для печати на основе элементов в контекстной карте необходимо сделать два изменения:
Во-первых, ключи контекстной карты должны быть в кавычках символов 'et
ине et
, или ключевые слова. Это потому, что возвращаемая карта пытается оценить символы без кавычек во время выполнения, которые не связаны (предполагая, что у вас нет некоторого глобального контекста, в котором они связаны, что не было предоставлено).
Во-вторых, вам нужно перебрать каждую карту внутри возвращаемой функции и извлечь соответствующие значения.Помимо изменения ключей карты с символов на ключевые слова, единственными другими изменениями являются uia
в соответствии с запросом, и для меня было проще всего сохранить изменения в любом случае.
(defmacro block [ctx & expr]
`(let [~@(mapcat (fn [[k v]] [k v]) ctx)] ~@expr))
(defmacro uia [metadata ctx arity & expr]
`(block ~metadata
(fn ~arity
(doseq [m# ~ctx]
(prn "got" ~arity (:et m#) (:s m#) ~'mt)))))
(def auto1
(uia {mt "dt"}
[{:et "wa" :s "a1"}
{:et "wa" :s "a2"}
{:et "um" :s "a3"}]
[et1 id cid]
(block {} (prn "auto1"))))
(let [myarr ["x" 11 22]] (apply auto1 myarr))