5 ms·
Agree with most of them, except, Advise against higher order functions. Higher order functions separate clojure from other languages, and is one of defining fe
by abc_lisper 9y ago
Agree with most of them, except,
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.
- adambard 9y agoI for one enthusiastically agree with the author's advice to use the `#()` syntax in place of `partial` and/or `comp`. It's just plain easier to parse, even for those who are familiar with higher-order functions but especially for those that aren't.
- bilboa 9y agoExactly. The author wasn't advising against using higher order functions in general, just certain ones like comp and partial, which are easily replaced by anonymous functions. I.e. (comp a b) is the same as #(a (b %)), so why not use the latter if it's easier to understand. I don't completely agree with the author on this point, but I know he wasn't against higher order functions.
- nickfargo 9y agoThat's interesting, because I find #() rather less easy to parse compared to (comp) or (partial) for otherwise equivalent expressions. 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.
- jraines 9y agoA happy medium IMO is to give the function resulting from `partial` or `comp` a name in a let binding. If it takes one arg, great; if it doesn't then the #() form with the named fn inside still a little shorter & easier to parse. This is inline with the other advice that brevity isn't the main virtue for readability.
- chc 9y agoBased on the examples presented, it seems like the OP doesn't actually mean "higher-order functions" in general. The "good" example still uses map, which is a higher-order function. It seems like what OP has a problem with is specifically functions that return functions.
- KurtMueller 9y agoSo basically he'd be against currying? I find currying useful in certain situations - threading/piping being a common scenario.
- chc 9y agoCurrying and composition, I think. 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.
- daxfohl 9y agoI frankly don't like these features even in Haskell. There are a few specific places where it makes things more elegant, but in general I dislike having to think about "how do I arrange params to allow for the greatest possible use of partial application in the rest of my code?", and then the inevitable "oh I can fix that with (flip (flip flip))" or some nonsense. It's tangential to the requirements of getting my app done, and generally time / brain cells wasted. I'd rather it simply not be part of the language in the first place. Granted most of my Haskell work is in boring line of business apps, so maybe partial application is more important in other fields.
- Silhouette 9y agoIt's one of those things where you can take a simple tool and probably make something hideously complicated with it if you go too far, but in simple cases it's useful all over the place. 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.
- lacampbell 9y agoHigher order functions separate clojure from other languages 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.
- posterboy 9y agodoes C's qsort count?
- lacampbell 9y agoI'd draw the line at that. But every corporate programming language has lambdas you can pass around as data now.
- emidln 9y agoI'd go so far as to advise aggressive use of the threading macros in order to remove visual nesting. It is much easier to read: (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))))
- jwdunne 9y agoWithout much Clojure experience, I agree. Sequential, what-comes-first, is easier to read than finding the first evaluated expression and peeling backwards just to build the same mental model.
- devin 9y ago-> and ->> are not equal to some->, cond->, etc. Threading enhances readability so long as it is not overused.