Idiomatic way to wrap object into collection (if it's not a collection already) in Clojure?

本秂侑毒 提交于 2021-02-10 18:36:52

问题


I have (for instance) a mix of data structures such as {:name "Peter" :children "Mark"} and {:name "Mark" :children ["Julia" "John"] i.e. :children value is either a single string or a collection of strings. Other functions in my code expect that the value of :children is always a collection of strings, so I need to adapt the data for them.
Of course I can use something like:

(defn data-adapter [m]
  (let [children (:children m)]
    (assoc m :children 
             (if (coll? children) 
               children
               [children]))))

But is there a more idiomatic/laconic way?


回答1:


I think you will have to take no for an answer.

(if (coll? x) x [x]) is about as terse and expressive as it gets. It’s what people usually use for this problem (sometimes with sequential? instead of coll?).

cond-> enthusiasts like me sometimes try to use it in place of a simple conditional, but here it is no improvement:

(cond-> x (not (coll? x)) vector)

In the context of your code, however, you can do a little better. A lookup and association is best expressed with update:

(defn data-adapter [m]
  (update m :children #(if (coll? %) % [%])))



回答2:


the only advice would be to abstract that logic to some function, to keep your actual business logic clean.

(defn data-adapter [m]
  (let [children (:children m)]
    (assoc m :children (ensure-coll children))))   

or, more concise, with update:

(defn data-adapter [m]
  (update m :children ensure-coll))

where ensure-coll could be something like this:

(defn iffun [check & {:keys [t f] :or {t identity f identity}}]
  #((if (check %) t f) %))

(def ensure-coll (iffun coll? :f list))

(or whatever another implementation you like)

user> (data-adapter {:children 1})
;;=> {:children (1)}

user> (data-adapter {:children [1]})
;;=> {:children [1]}


来源:https://stackoverflow.com/questions/59453099/idiomatic-way-to-wrap-object-into-collection-if-its-not-a-collection-already

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