Fork me on GitHub
#specter
<
2018-01-18
>
jose11:01:47

hi, first of all, I'm really enjoying specter and how easy makes many things, but I have a case where I'm thinking that maybe is better to not use specter. I have a map where I want to remove and rename some keys. e.g. with specter:

(->> {:id 1 :data_val 5 :bad nil}
    (s/select-one (s/submap [:id :data_val]))
    (s/transform [s/MAP-KEYS] #(case % :data_val :value %))
and without
(-> {:id 1 :data_val 5 :bad nil}
    (select-keys [:id :data_val])
    (clojure.set/rename-keys {:data_val :value}))
what do you think? makes sense to use specter here? Is there a better way to do it with specter?

souenzzo14:01:12

Almost the same perf I think that w/o spec is more readable, in this case.

(time
  (doseq [i (range 1000000)]
    (->> {:id 1 :data_val 5 :bad nil}
         (s/select-one (s/submap [:id :data_val]))
         (s/transform [s/MAP-KEYS] #(case % :data_val :value %)))))
"Elapsed time: 1031.939844 msecs"
=> nil
(time
  (doseq [i (range 1000000)]
    (-> {:id 1 :data_val 5 :bad nil}
        (select-keys [:id :data_val])
        (clojure.set/rename-keys {:data_val :value}))))
"Elapsed time: 1794.127254 msecs"

souenzzo14:01:01

Mine is a bit faster. And has data/explicit params.

(let [n 10000000]
  (prn "specter")
  (time
    (doseq [i (range n)]
      (->> {:id 1 :data_val 5 :bad nil}
           (s/select-one (s/submap [:id :data_val]))
           (s/transform [s/MAP-KEYS] #(case % :data_val :value %)))))
  (prn "@souenzzo")
  (time
    (doseq [i (range n)]
      (let [from->to {:data_val :value
                      :id       :id}]
        (reduce-kv (fn [acc k v]
                     (if (contains? from->to k)
                       (assoc acc (from->to k) v)
                       acc)) {} {:id 1 :data_val 5 :bad nil})))))

jose21:01:54

@U2J4FRT2T thanks for your example, didn't know about reduce-kv