(def good-set-of-stuff
(->> stuff
(filter good?)
(map enrich)
(into #{}))
than it is to read: (def good-set-of-stuff
(into #{}
(map enrich
(filter good? stuff))))
or (def good-set-of-stuff (into #{} (map enrich (filter good? stuff))))I actually think he has a point on those two in the context of Clojure specifically. The process of explicitly currying or composing functions (again, in Clojure specifically) is usually more verbose and IMO harder to read than just writing an anonymous function that expresses the same thing.
Granted most of my Haskell work is in boring line of business apps, so maybe partial application is more important in other fields.
For example, I very often write functions that take an initial parameter representing some sort of customisable context and then further parameters that are the right types to use with some standard higher order function like a map, filter or fold. Partial application then supplies the context and gives back something ready to pass into that HOF.
I just find the "plain_fn <$> weird_type <*> weird_type ..." e.t.c really convenient.
It's incredibly convenient to use, but sometimes when I look at 'idiomatic' React code, in particular in the context of Redux, I can't help but feel it's a bit too much, especially when I look at the code through 'teacher' eyes, and especially when it's combined with JSX. And that's not even mentioning the arrow function variants, default parameters, and other ESNext goodies.
And yet I find it difficult to keep my hands off it, because it's just so damn convenient.
"Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. "
-- Antoine de Saint-Exupery
At a glance I know that (comp f g h) and its flat list of arguments expresses a simple function composition chain. Seeing a #(f (g (h %))) where (comp) will do makes me sift through more parens; more than that though, when (comp) is embraced as convention, a #() is an immediate cue that simple function composition is not what's being expressed, which draws me in necessarily to examine the particular structure of the #() body.
I don't know if that's true anymore. HoF are becoming mainstream - and rightly so.
Java, C++, Python, C#, VB.NET, Javascript, PHP, Perl, Ruby.. they all have them.
But every corporate programming language has lambdas you can pass around as data now.
Advise against higher order functions. Higher order functions separate clojure from other languages, and is one of defining features of this class of languages.
Advise to not use threading. Threading is just a series of steps. I find it very readable. If I start using symbols the step sequence can become a step graph FWIW.