Should the docstring of empty? change, since the advice to use (seq ...) as a replacement for (not (empty? ..)) no longer holds for counted? collections that aren't seqable in clojure 1.12?
clj-kondo warns against (not (empty? ...)) because of the docstring in empty? . I think discussions about this could be ended once and for all if core has a not-empty? function.
I know there is not-empty as well but this isn't updated to do what empty? in clojure 1.12 does and doesn't return a boolean which is what some people want (https://twitter.com/ryrobes/status/1595923346700599298).
it did change slightly, but seq is still the preferred idiom in seq contexts (which is how the docstring now reads)
http://clojure.github.io/clojure/branch-master/clojure.core-api.html#clojure.core/empty?
makes sense
perhaps the linter could be more nuanced in this case, and only apply if x is a seq (and not a seqable)?
yeah
hm?
I didn't understand the "and not a seqable" part
like if x is a vector, then it is seqable, but it is not a seq
so in the case of (not (empty? a-vector)), maybe this warning no longer applies
but if you have (not (empty? (filter ...))) it would
I have the suspicion that most people wouldn't really care about this
this is why I think a built-in not-empty? that did the right thing always would help
I would still say you should use seq in a seq context, even if not-empty? existed
the "right thing" is contextual and depends on semantics
the right thing when you just want a boolean check (which the ? indicates)
I'll try to make the linter more sophisticated. it could warn only when the argument is already a seq (and not a counted)
so the warning here would disappear: (not (empty? []))
but I still have a hard time convincing people running into this about the importance of it 😅
I made an issue for it here earlier: https://github.com/clj-kondo/clj-kondo/issues/1743
Is the issue with (not (empty? already-a-seq)) that seq is being called twice?
isn't (seq already-a-seq) just obviously better in being more concise?
I have experienced that people don't find this obviously better - e.g. read the tweet I linked in the original post
that person is wrong /shrug
Clojure embraces nil punning and logical truth values for seqs
the clojure shibboleth :)
I'm assuming that tweet is referring to code where this is a conditional pred, and imho seq is absolutely the right thing to call in that circumstance both aesthetically and for performance (assuming x is a seq)
well, since it's in the docstring, I'll leave it in clj-kondo. I'm a happy seq user but even in core libraries I've seen usages of (not (empty? ...))
it has always bugged me (pre 1.12) to call seq in this circumstance when x is not already a seq. doing seq coercion is not necessarily fast for an arbitrary coll
and those are cases where I would call (not (empty? )) or (= 0 (count x))
or (zero? (count x))?
yeah
zero? is actually optimized so that's better
hmyeah, so it's a bit nuanced
or I would use empty? and flip the cases
I think empty? is semantically the cleanest thing to say for a collection
(if (empty? ...) x y)I think what people want is “empty?/not-empty” to be like “conj”—just do the fastest thing for this type. The “use the (seq x) idiom” has always bothered me precisely because it is for seqs and so can never have polymorphic fast paths for empty checking like ”empty?” can.
I don't want that
more specifically, I don't want to lose seq idioms. I do want to enable efficient collection without coercion to seq when you know that's what you have
empty? now takes advantage of faster paths for counted colls when it can
That’s great, but people took the wrong lesson from the previous docstring
Using seq for empty check is like using cons for conj
I'm not sure at this point whether you are satisfied with the 1.12 endpoint
I am. I’m just frustrated this didn’t happen sooner and the (seq x) reflex has to be unlearned
I do wonder if empty? should mention seq at all; or if seq should say “prefer empty? unless you know you have a seq”
Remember this convo started with a linter rule scolding someone for using empty?
well, we didn't know if that person was already using 1.12 or if their input was already a seq :)
but I will change clj-kondo so it will only "complain" if the input is surely a seq
but even then using (not (empty? ...)) on a seq isn't the end of the world. calling seq on an already-seq is cheap, I assume
Not blaming you at all @borkdude :)
so perhaps I should disable the linter altogether and make it opt-in
well, it's not about blame, but about making clojure a better experience, let's focus on that :)
But you’re picking up on community idioms that (imo) were already too scolding, and they emerged because empty? actually wasn’t any different till now and the docstring was really pushing you away from it
Anyway I’m very happy about this change. I had a cempty? function I copied around that I will no longer need
“Counted empty”