6 ms·
The thing to understand about Clojure is that its creator/maintainer believes software tools should almost never deprecate features. Because of this, there are
by drcode 7y ago
The thing to understand about Clojure is that its creator/maintainer believes software tools should almost never deprecate features. Because of this, there are a few esoteric functions and features that were created in the language along the way that will likely always remain in the language- The two examples given by OP arguably fall into that category, though I'm sure someone in this thread will attempt to argue that every-pred & some-fn are essential features for the core language.
Other oddities include juxt, areduce, fnil, nthnext, derive, seque, and by now arguably the whole "ref" memory system (since Software Transactional Memory has pretty much gone by the wayside as a desirable programming feature)
Of course, Rich Hickey has also been very good at deciding which features to put into the language in the first place, so the number of legacy oddities is pretty tiny anyway, fewer than most languages.
- thom 7y agoI don't see why these are so weird, logical composition of predicates is really common.
- drcode 7y agoHmm... I guess that's a valid point, though I would never use them for logical composition simply because the names of these functions really hurt readability: They are basically higher-order versions of "and" and "or", maybe if they had those words in their name they would be less cumbersome.
- disconcision 7y agoI think 'every' and 'some' are reasonable analogues, but the choice to make the implementations and hence their suffixes asymmetric wrt 'truthiness handling' is confusing to me, especially since these functions have existed (symmetrically) for a while in various schemes under the names 'conjoin' and 'disjoin'
- drcode 7y agoI agree that I'd be far more likely to use these if they were named "conjoin" and "disjoin".
- TeMPOraL 7y agoThese names are even worse. I know Clojure likes this style, but to me, "conjoin" is just a fancy way of writing "join" if you want another distinct symbol naming the same, very generic concept. "some" and "every" create nicely readable code. "every-pred" and "some-fn" could be called "satisfies-every" and "satisfies-some", respectively.
- fogus 7y agoI wrote both of these functions and conjoin and disjoin were definitely considered but were ultimately dismissed to avoid confusion with `conj` and `disj`. The chosen names were meant to echo `some?` and `every?`.
- thom 7y agoI personally don't find it that hard remembering them. I am sure all of Clojure's names could be more regimented, but I will still never forget how much I laughed when someone tried to tell me how well designed the Haskell lens operators were: https://hackage.haskell.org/package/lens-4.18.1/docs/Control-Lens-Operators.html https://hackage.haskell.org/package/lens-4.18.1/docs/Control...
- tome 7y agoThis article explains the rationale behind the naming scheme. It's quite regular. https://gist.github.com/ChrisPenner/1f7b6923448b3396a45d04a2b6b9d066#optics-by-example-cheat-sheets https://gist.github.com/ChrisPenner/1f7b6923448b3396a45d04a2...
- thom 7y agoYes, I understand it's regular. It doesn't stop it being an absolute abomination. My point is that having regularity in naming doesn't stop an API being horrible, and not having regularity in naming doesn't _make_ an API horrible.
- 77544cec 7y agoIndeed this is one of the first steps Paul Graham goes through in On Lisp.
- tprice7 7y agoAre there more recent features of Clojure that you think have made every-pred and some-fn less useful? I'm curious what they are if that is the case.
- drcode 7y agoSo, for the every-pred example, I'd prefer to use clojure piping for better readability: (->> people (filter :admin?) (filter :mod?)) This is admittedly a matter of taste, though. For the some-fn example, I would argue that the usage in OP is a very idealized and tuned example... how often do you really want to say "try this one predicate and if that doesn't work, try this other one"? I only need to do that maybe a couple of times a year (when parsing some sort of irregular raw data) so it's rare enough that I'd prefer to write the predicate explicitly instead of using this sort of succinct predicate composition that could become a "head-scratcher" at a future date.
- TeMPOraL 7y agoNice feature of doing it like in the post: (filter (every-pred :admin? :mod?) people) is that a) this arguably conses less, by building only one results list, and b) :admin? and :mod? are just regular arguments, which means they could be replaced by data. I'm thinking of: (let [acl [:admin? :mod?]] (filter (apply every-pred acl) people)) This capitalizes on Clojure's interesting design decision in which when funcalled, a :keyword resolves to function that gets an element with the name :keyword from the map passed as the argument.
- drcode 7y agoI admit a case can be made for having every-pred in the language, since from a mathematical standpoint predicate composition is an innate low-level feature (putting the questionable naming issue aside)
- int_19h 7y ago> this arguably conses less, by building only one results list Aren't lazy sequences idiomatic in Clojure?
- dustingetz 7y ago> Rich believes software tools should almost never deprecate features This is pretty severely mis-stated He believes the core of a dynamic programming language (specifically the core) has a very high bar for stability in order to avoid a number of problems that other dynamic languages have. This intersects with a number of other ideas, for example Lisp macros can extend syntax from a library and thus keep the change-restricted surface area small since almost anything can be implemented in a library. I think, don't recall a smoking gun quote for this, correct me if I'm wrong.
- drcode 7y agoHave you watched his "spec-ulation" talk? It makes a very strong case against EVER removing a feature from an API. https://www.youtube.com/watch?v=oyLBGkS5ICk https://www.youtube.com/watch?v=oyLBGkS5ICk
- jdminhbg 7y agoIf you check his remarks from Spec-ulation (https://www.youtube.com/watch?v=oyLBGkS5ICk https://www.youtube.com/watch?v=oyLBGkS5ICk), he also thinks just plain old libraries should not remove or change functionality, but only accrete. If you want to make a breaking change, you should change the name of the library. You can see this philosophy in practice with clojure.spec.alpha-2: https://github.com/clojure/spec-alpha2 https://github.com/clojure/spec-alpha2
- gowld 7y agoThat's SemVer with the version in the name.