clojuredesign-podcast

Discussions around the Functional Design in Clojure podcast - https://clojuredesign.club/
Stefan 2020-09-08T20:01:48.036500Z

@neumann @nate This week I listened to the episode on partial . I didn’t quite get the part about partial apply in a thread, but besides that, it occurred to me that you can use partial in a thread-first to sneak in a function that expects the injected param last by partial applying all the args except the last one, so that in effect it becomes also the first. So something like:

(-> value
    (assoc ...)
    (partial map some-fn))
Is this something you would expect to see in production code? Is it “cheating” / confusing? Thanks!!!

nate 2020-09-08T20:07:01.036600Z

the way I've accomplished that in the past is to just use the thread last macro. I forget who it was that I first heard that from, but it might be a Stuart Sierra tweet. For example:

(-> value
    (assoc ...)
    (->> (map some-fn)))

nate 2020-09-08T20:07:27.036800Z

I remember liking it a lot when I first heard about that trick

nate 2020-09-08T20:08:28.037Z

but now, I generally don't mix -> with ->>, unless it's in exploratory fiddle code, because of the mental leap between "operating on an entity" and "operating on a list"

neumann 2020-09-08T20:08:31.037200Z

@stefan.van.den.oord Thanks for listening! I think you're missing a set of parens.

user=> (-> {:foo 1} (assoc :bar 2) ((partial map key)))
(:foo :bar)
I also concur with @nate that the ->> trick is easier for me to understand.

neumann 2020-09-08T20:11:04.037400Z

@stefan.van.den.oord Here's a use of partial apply too:

user=> (def max-list (partial apply max))
#'user/max-list
user=> (max-list [1 2 3 4 5])
5
user=> (max 1 2 3 4 5)
5

neumann 2020-09-08T20:11:53.037600Z

Since max takes a variable number of parameters, you can use partial apply to create a function that expects a seq.

neumann 2020-09-08T20:13:33.037800Z

And if you want to use max in threading, that's where the apply comes in:

(->> [{:name "Foo" :age 32} {:name "Bar" :age 64}]
     (map :age)
     (apply max))

Stefan 2020-09-08T20:19:24.038200Z

Ok, got ya on the thread first/last, I understand what you mean and it sounds like a sensible thing not to mix them, so I’ll also go with that 🙂 As for the partial apply IIRC you explicitly mentioned using that as a last statement in a thread, but as also in your example above you don’t need partial in that case. Or am I misremembering and/or misunderstanding?