0

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"))
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Nile
  • 386
  • 5
  • 15

1 Answers1

1

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))
shock_one
  • 5,845
  • 3
  • 28
  • 39
  • thanks a log. ```(apply (partial velocity/render "test.vm") (get-data)) ``` works fine. – Nile Dec 20 '13 at 06:11
  • `(apply hash-map kvls)` will _not_ work. `hash-map` does not take map entries in vector form. either `kvls` must be replaced with `(flatten kvls)` or the line must be replaced with `(into {} kvls)` because `into` uses `conj` which accepts map entries in vector form. – Leon Grapenthin Dec 20 '13 at 06:30
  • lgrapenthin, hash-map won't see a vector: apply will convert it to a parameters list. Try to execute it by yourself: `(apply hash-map [:a 1 :b 2])` – shock_one Dec 20 '13 at 07:18