convex
convex copied to clipboard
Is `disj` necessary anymore?
Sets are now considered as maps of value -> true. Since it is now possible to do (assoc #{} 42 true), it looks like disj is not needed anymore. It would be more consistent to make dissoc work with sets.
Sounds sensible. Though Sets are not exactly equals to such maps, they behave differently for various functions (map?).
Might be worth keeping disj as an alias for a unified dissoc for familiarity with Clojure users? Though that would potentially be a violation of the simplicity principle....
On one hand, it is true that you cannot always dissoc on something that you can assoc on (eg. vectors). On the other hand, I see dissoc as having the hability to remove any element. I suspect the only reason Clojure has disj is because you cannot (assoc #{} :foo true). Since we can, I cannot see a valid reason for keeping it. Convex is sufficiently different from Clojure that I wouldn't mind removing it.
After some reflection, I am thinking we should keep this for now for a few reasons:
- Logically, each of the major collection types has different removal semantics (
dissoca whole entry for Maps,disja single element for Sets,dropandtakefor Vectors and Lists) - It is familiar to Clojure users
- There is potentially a slight performance benefit from specialised
dissocvs.disj, since Maps and Sets have different interfaces for removal - It gives a bit better type safety and more consistent type signatures
Writing doc, I keep bumping into that kind of considerations.
First and foremost, I guess what bothers me most is that sets can use assoc to remove a value while not supporting dissoc. I'd rather prefer removing support for assoc, leaving conj as the idiomatic function.
I think the important thing is the we establish logical abstract types and that core functions work consistently on them.
disj is Set specific, so no problem. It's the inverse of conj in the context of Sets. It also has a very specific usage of converting nil to the empty Set (effectively a Set coercion on the input, since Set functions generally treat nil as the empty Set).
assoc and dissoc seem logically part of an "Associative" abstraction, that maps keys to values. If we take that position, options seem to be:
- We could conclude that
Setshould not be considered Associative, and hence lose bothassocanddissoc. - We could accept that
dissocis not symmetric. It already doesn't work for Vector.... - We could make Associative
dissocwork the same asdisjwith Sets.
Alternatively we could say that dissoc is Map specific like disj is Set specific.
4. I think this is current behaviour?