clojuredesign-podcast

Discussions around the Functional Design in Clojure podcast - https://clojuredesign.club/
Stefan 2020-11-20T10:19:34.111300Z

How would you write a function that does this: based on some parameters, it produces a map. IF one of the parameters is non-nil, THEN the map needs to contain an extra key/value pair based on that parameter. I can do something like this:

(defn myfun [a b]
  (let [result {:a a
                :foo (foo-fun a b)
                :bar (bar-fun a b}]
    (if b
      (assoc result :b (extra-fun b)) 
      result)))
or:
(defn myfun [a b]
  (merge {:a a
          :foo (foo-fun a b)
          :bar (bar-fun a b}
         (when b {:b (extra-fun b)})
or:
(defn myfun [a b]
  (let [result {:a a
                :foo (foo-fun a b)
                :bar (bar-fun a b}
        result (when b (assoc result :b (extra-fun b)))]
    result))
And I could probably come up with half a dozen more ways to write it. How would you write it?!

Chris Emerson 2020-11-20T11:07:22.111700Z

I'd go with option b personally, not sure if there are better ways of writing it

dharrigan 2020-11-20T12:07:11.111900Z

b for me

2020-11-20T13:00:11.114200Z

cond-> might be an option as well

(defn myfun [a b]
  (cond-> {:a a
           :foo (foo-fun a b)
           :bar (bar-fun a b)}

           b (assoc :b (extra-fun b))))

lodin 2020-11-20T13:27:54.115800Z

@stefan.van.den.oord The last alternative returns nil if b is false, in contrast to the first two. (Note that you're testing against truthiness, not against nil, but I assume b isn't a bool.)

lodin 2020-11-20T13:28:51.116600Z

I would also go with the second alternative. But, does it matter if :b is present and nil?

lodin 2020-11-20T13:32:30.117400Z

So,

(defn myfun [a b]
  {:a a
   :foo (foo-fun a b)
   :bar (bar-fun a b)
   :b (when b
        (extra-fun b))})
instead. Or I guess you'd want the key to be named extra, now that I think about it.

skuro 2020-11-20T14:13:12.119800Z

not exactly the same problem, but I have written this in a few projects already

(defn maybe-assoc
  "Assocs value v at key k to a map only if v is not `nil`"
  [m k v]
  (cond-> m
    (some? v)
    (assoc k v)))
I would probably have a maybe-update flavor of the above for this case, accepting a function as input