2

I am currently developing a small CMS using the wonderful Enlive as templating engine. Enlive has a macro called at that takes a node (a map) specifying the HTML snippet and an arbitrary number of tuples each consisting of a selector (a vector) and a transformation (a closure).

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

Now I want to generate the tuples depending upon incoming data/context. I have tried a lot of different things without success. For example

(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))))))

Any help is highly appreciated.

-Jochen

1
  • I suggest looking at the macroexpansion. at the repl: macroexpand-1; in SLIME: slime-macroexpand-1. It may be that you're creating the form incorrectly. Commented Jul 25, 2011 at 15:34

2 Answers 2

1

Clojure is a Lisp, so you can always fallback to building the code you'd want as a list, and call eval on it. I'm not 100% sure about the code you gave, but I'd guess you just want to enclose your whole syntax-quote in an eval call.

(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)))))))
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, eval solved the problem. I did also some quoting wrong. Using at* form was also a piece of the puzzle. Thanks!
1

Not sure if they are interchangeable, but take a look at the at* function. Seems to me that your problem is at being a macro.

EDIT: They're not. Call it like this:

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

1 Comment

Thanks for taking care. (at {:tag :p} [:p] (content "foo")) gives me ({:content ("foo"), :tag :p}) as expected. Unfortunately (at* {:tag :p} [[:p] (content "foo")]) throws "Don't know how to create ISeq from: clojure.lang.Keyword".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.