Как генерировать аргументы макроса Clojure динамически? - PullRequest
2 голосов
/ 23 июля 2011

В настоящее время я разрабатываю небольшую CMS, используя замечательный Enlive в качестве движка шаблонов.В Enlive есть макрос at, который принимает узел (карту), задающий фрагмент HTML, и произвольное количество кортежей, каждый из которых состоит из селектора (вектор) и преобразования (замыкание).1006 * Теперь я хочу генерировать кортежи в зависимости от входящих данных / контекста.Я перепробовал много разных вещей без успеха.Например

(let [this (repository/u "http://example.com/ACMECorp")
      statements (repository/find-by-subject this)
      context {:depth 1}]
  `(at (snippet-for 'this 'context)
       [root] (set-attr :about (str 'this))
       ~@(loop [rules []
                st statements]
           (if-not (seq st)
             rules
             (recur (conj rules
                          `[:> (attr= :property ~(str (repository/predicate (first st))))]
                          `(content (renderit ~(repository/object (first st)) 'context)))
                    (rest st))))))

Любая помощь высоко ценится.

-Jochen

Ответы [ 2 ]

1 голос
/ 24 июля 2011

Clojure - это Lisp, так что вы всегда можете вернуться к созданию кода, который вы хотите получить в виде списка, и вызвать eval для него. Я не уверен на 100% в коде, который вы дали, но я предполагаю, что вы просто хотите заключить всю синтаксическую цитату в вызов eval.

(let [this (repository/u "http://example.com/ACMECorp")
      statements (repository/find-by-subject this)
      context {:depth 1}]
  (eval `(at (snippet-for 'this 'context)
             [root] (set-attr :about (str 'this))
             ~@(loop [rules []
                      st statements]
                 (if-not (seq st)
                   rules
                   (recur (conj rules
                                `[:> (attr= :property ~(str (repository/predicate (first st))))]
                                `(content (renderit ~(repository/object (first st)) 'context)))
                          (rest st)))))))
1 голос
/ 24 июля 2011

Не уверен, что они взаимозаменяемы, но взгляните на функцию *. Мне кажется, что твоя проблема в том, чтобы быть макросом.

РЕДАКТИРОВАТЬ: Они не. Назовите это так:

(at* a-node
  [[:a :selector] a-transformation
   [:another :selector] another-transformation
   ...])
...