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?
(defn params-test [a & kvls]
(println (apply hash-map kvls)))
(defn get-data []
[:a "A"])
(defn test[]
(params-test (get-data))
No value supplied for key:((:a "A"))
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))