1

I have a function like this:

pdfkit-clj.core/gen-pdf
 [html & {:keys [path tmp asset-path stylesheets margin orientation page-size], :or {path (:path defaults), tmp (:tmp defaults), asset-path (:asset-path defaults), margin {}, orientation (:orientation defaults), page-size (:page-size defaults)}}]

Now I'm trying to pass it a map with keyword arguments which doesn't work.

(let [gen_pdf_args {:tmp tmp_dir
                     :margin {:top 0 :right 0 :bottom 0 :left 0}}] 
        (gen-pdf html-black gen_pdf_args)
)

This issue is similar to turning a list into arguments.

m33lky
  • 7,055
  • 9
  • 41
  • 48
  • The first linked question has three different approaches to solving the problem; I agree with the top answer that the best approach is to stay out of this situation by not writing functions to take unrolled keyword args, but if you can't change the function's interface then I think the second linked question has the best answer for how to work around the problem. – amalloy May 16 '17 at 16:23

2 Answers2

3

Using & {:keys [...]} actually doesn't expect you to call it with a map. Instead, you call it like (gen-pdf html :tmp tmp_dir :margin {:top 0}).

If you really want to use your map, you can use apply and flatten like (apply gen-pdf html-black (-> gen_pdf_args vec flatten)).

Alejandro C.
  • 3,771
  • 15
  • 18
1

It sounds like you want something similar to the keyvals function:

(keyvals m)
 "For any map m, returns the keys & values of m as a vector,
  suitable for reconstructing via (apply hash-map (keyvals m))."

(keyvals {:a 1 :b 2})
;=> [:b 2 :a 1]
(apply hash-map (keyvals {:a 1 :b 2}))
;=> {:b 2, :a 1}

Notice that you still need to use apply like Alejandro said. You can find more information on keyvals here.

Alan Thompson
  • 29,276
  • 6
  • 41
  • 48