Fork me on GitHub
#beginners
<
2023-04-06
>
Ryan16:04:03

I routinely need to put big maps toghether to send to web services, and I have yet to find a satisfying way to achieve the following: (defn some-fn [{:keys opt1 opt2 opt3 req1 req2 req3}])

seancorfield16:04:23

Since that isn't legal Clojure syntax, can you provide a bit more detail about what you're trying to achieve and a more concrete example?

Ryan16:04:58

Yeah sorry I hit enter too soon and am in middle of adding the rest 🙂 stupid return vs. shift+return 🙂

Ryan16:04:15

So a fn like this:

(defn ex [{:keys [req1 req2 req3 opt1 opt2 opt3]}]
  (let [result {:req1 req1 :req2 req2 :req3 req3}
        result (if (some? opt1) (conj result {:opt1 opt1}))
        result (if (some? opt2) (conj result {:opt2 opt2}))
        result (if (some? opt3) (conj result {:opt3 opt3}))]
  result
    ))
There are a bunch of approaches that look promising, but I can’t decide between them all.

Ryan16:04:08

If it were only as simple as having a backend service that was cool with :opt1 nil .. but no such luck.

seancorfield16:04:28

(defn ex [{:keys [opt1 opt2 opt3] :as data}]
  (cond-> (select-keys data [:req1 :req2 :req3])
    (some? opt1) (assoc :opt1 opt1)
    (some? opt2) (assoc :opt2 opt2)
    (some? opt3) (assoc :opt3 opt3)))
Is that more appealing?

👍 2
Ryan16:04:46

Oooh yes that’s lovely.

seancorfield16:04:16

If optN is not boolean, you could just use optN instead of (some? optN) in each case.

Ryan16:04:42

something about endlessly bouncing result along the let block felt off

seancorfield16:04:05

If you have a lot of optional keys, you could reduce over them and conditional assoc in each non-`nil` value from data.

(defn ex [data]
  (reduce (fn [result k] (if-some [v (get data k)] (assoc result k v) result))
         (select-keys data required-keys)
         optional-keys))

🙏 2
Ryan16:04:26

medley looks like its packed full of a couple things I’ve crudely done in my util ns 🙂 thanks for the pointer

Ryan16:04:04

I need to think to use reduce more! I do end up with a lot of optional keys for this particular problem

andre16:04:41

Can't recall how many times I added assoc-some to my project. Sounds like a super common use case, would be awesome if it could be on clojure.core

pppaul16:04:01

assoc-some's effect can be delayed, if you are ok filtering out nil values from your return object. sometimes that's not a good option. cond-> acts are a good alternative, and if you go to the extreme, you may be interested in a schema based solution or something like pathom (rule engine solution). it all depends how much of a pain in the ass this stuff is in your codebase

andre16:04:47

filtering out nil values is almost never an option in my experience, because you don't really know if that key is nil because it shouldn't exist, or if it is nil because nil is the actual value you want for that key

Ryan16:04:13

@U0LAJQLQ1 ooh good food for thought.. I believe schemas will be coming to this codebase sooner or later, just a bit of analysis paralysis between Schema, Malli, Spec, for doing that sort of thing

pppaul16:04:45

malli is very nice

andre16:04:06

And I usually use assoc-some when I'm constructing some data to match a certain schema with optional keys. I still use it very often even using schema libs.

Ryan17:04:25

Yeah and payload-wise its a drop-in-the-bucket compared to the material design icon library’s giant collection of svg path data (can’t really tree-shake it either since the icons we’re using arem’t predictable

Ryan17:04:33

Thanks for all the help 🙂

skylize14:04:17

> Yeah sorry I hit enter too soon and am in middle of adding the rest 🙂 stupid return vs. shift+return 🙂 Click <user icon in top-right corner> --> Preferences --> Advanced. You should find a setting that reads: > When writing a message, press Enter to… > ● Send the message > ⚬ Start a new line (use Ctrl Enter to send) Click on the second one to swap the active radio button. Then click the 𝖷 or press Esc. You should be free of this frustrating default behavior.

🙌 2