Clojure applying a map and keyword arguments destruction

坚强是说给别人听的谎言 提交于 2019-12-09 08:33:48

问题


Consider a function with the following signature:

(defn make-widget [& {:keys [x y] :or {x 10 y 20}}]
 ...)

What is the best way to pass a map to the function, e.g.:

(make-widget {:x 100})

or

(make-widget {:y 200 :x 0})

What I have currently thought of is via vec, flatten and apply e.g.:

(apply make-widget (flatten (vec ({:x 100}))

I strongly believe there is a better way to do this. Can you please consider one?


回答1:


I can't think of a more elegant way, either, though it seems to me to that there should be one (like a map-specific variant of apply).

Using flatten has problems beyond not being very elegant, though. If the values of your map are collections, flatten will work recursively on those, too, so things could get totally mixed up. This alternative avoids that problem:

(apply make-widget (apply concat {:x 100}))



回答2:


There is also a known (not invented by me at least), function "mapply":

(defn mapply [f & args] (apply f (apply concat (butlast args) (last args))))

which can be applied like

(mapply your-function {:your "map"})

As to why is this language-specific functionality absent from Clojure core, being implemented more natively and elegantly, no one could ever give me a clear answer.

UPDATE

After I have spent much time programming in Clojure, I personally tend to refrain from creating functions that accept a {} as a vararg. Although at first this can seem appealing, in reality experience proves that passing an explicit {} is always better for many reasons.




回答3:


You can use:

(apply make-widget (mapcat identity {:x 200 :y 0}))


来源:https://stackoverflow.com/questions/19375112/clojure-applying-a-map-and-keyword-arguments-destruction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!