I've got a simple to-float
function:
(defn to-float [v] (cond
(nil? v) nil
(string? v) (Float/parseFloat v)
:else (float v)))
And a record:
(defrecord Product [Id UseRecommendation ReferenceProductId OnePrice TotalPrice
ManualTotalPrice MarketTotalPrice PreviousTotalPrice PurchaseTotalPrice
Tax Deposit RuleId RoleId PrimaryProduct Size])
For some of the keys(?) I wish to make sure they are float before passing them to map->Product
(constructor?). Sorry I'm not familiar with the terminology here.
Anyway, my first solution was very verbose:
(defn init->Product [args]
(let [converted-args (assoc args
:TotalPrice (to-float (:TotalPrice args))
:ManualTotalPrice (to-float (:ManualTotalPrice args))
:MarketTotalPrice (to-float (:MarketTotalPrice args))
:PreviousTotalPrice (to-float (:PreviousTotalPrice args))
:PurchaseTotalPrice (to-float (:PurchaseTotalPrice args))
:Tax (to-float (:Tax args))
:Deposit (to-float (:Deposit args)))]
(map->Product converted-args)))
Second one was better but has lots of "noise" in terms of apply
, merge
, hash-map
and so forth:
(defn init->Product [args]
(let [apply-float (fn [keys] (merge args (apply merge (map #(hash-map % (to-float (% args))) keys))))]
(map->Product (apply-float '(:TotalPrice :ManualTotalPrice :MarketTotalPrice :PreviousTotalPrice :PurchaseTotalPrice :Tax :Deposit)))))
The third solution uses recursion, which isn't easy to comprehend for people who are new to Clojure either:
(defn init->Product [args-orig]
(let [apply-float (fn [args keys] (if (empty? keys) args (let [key (first keys)] (recur (assoc args key (to-float (key args))) (rest keys)))))]
(map->Product (apply-float args-orig '(:TotalPrice :ManualTotalPrice :MarketTotalPrice :PreviousTotalPrice :PurchaseTotalPrice :Tax :Deposit)))))
Can you think of something simpler? I have a feeling there exists an utility function I'm missing here, or I fail to see how reduce
or some other could be used.
Edit: This is more like how I would do it in Python
(defn init->Product [args-orig]
(let [apply-float (fn [args keys] (merge args (into {} (map (fn [key] [key (to-float (key args))]) keys))))]
(map->Product (apply-float args-orig '(:TotalPrice :ManualTotalPrice :MarketTotalPrice :PreviousTotalPrice :PurchaseTotalPrice :Tax :Deposit)))))