Question

I'm new to Clojure, and I am using ring.velocity to develop a webapp.

Here is my ring.velocity.core/render method:

(defn render
  [tname & kvs]
  "Render a template to string with vars:
    (render :name \"dennis\" :age 29)
   :name and :age are the variables in template.  "
  (let [kvs (apply hash-map kvs)]
    (render-template *velocity-render tname kvs)))

For this simple example, it works fine:

(velocity/render "test.vm" :name "nile")

But sometimes, we can't hard code the key value pairs. A common way:

(defn get-data [] {:key "value"}) ;; define a fn get-data dynamic.

(velocity/render "test.vm" (get-data));; **this go wrong** because in render fn , called (apply hash-map kvs)

Has the error:

No value supplied for key: ....

It looks like it is treated as if it was a single value. I've changed the type to [], {}, and (), but each of these fails.

My question is: What does & kvs in clojure mean? How can I dynamically create it and pass it to method?

ADD A Simple Test

(defn params-test [a & kvls]
   (println (apply hash-map kvls)))

(defn get-data []
   [:a "A"])

(defn test[]
   (params-test (get-data))

Result

 No value supplied for key:((:a "A"))
Was it helpful?

Solution

The problem here is that you're trying to create a hash-map from a single list argument instead of list of arguments.

Use

(apply hash-map kvls)

instead of

(hash-map kvls)

In your original question you can try to use apply with partial

(apply (partial velocity/render "test.vm") (get-data))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top