Fork me on GitHub
#clojure-dev
<
2022-11-26
>
borkdude14:11:47

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).

Alex Miller (Clojure team)14:11:05

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?

borkdude14:11:51

makes sense

Alex Miller (Clojure team)14:11:19

perhaps the linter could be more nuanced in this case, and only apply if x is a seq (and not a seqable)?

borkdude14:11:22

I didn't understand the "and not a seqable" part

Alex Miller (Clojure team)15:11:39

like if x is a vector, then it is seqable, but it is not a seq

Alex Miller (Clojure team)15:11:07

so in the case of (not (empty? a-vector)), maybe this warning no longer applies

Alex Miller (Clojure team)15:11:23

but if you have (not (empty? (filter ...))) it would

borkdude15:11:34

I have the suspicion that most people wouldn't really care about this

borkdude15:11:22

this is why I think a built-in not-empty? that did the right thing always would help

Alex Miller (Clojure team)15:11:35

I would still say you should use seq in a seq context, even if not-empty? existed

Alex Miller (Clojure team)15:11:09

the "right thing" is contextual and depends on semantics

borkdude15:11:27

the right thing when you just want a boolean check (which the ? indicates)

borkdude15:11:24

I'll try to make the linter more sophisticated. it could warn only when the argument is already a seq (and not a counted)

borkdude15:11:40

so the warning here would disappear: (not (empty? []))

borkdude15:11:54

but I still have a hard time convincing people running into this about the importance of it 😅

borkdude15:11:04

Is the issue with (not (empty? already-a-seq)) that seq is being called twice?

Alex Miller (Clojure team)15:11:46

isn't (seq already-a-seq) just obviously better in being more concise?

borkdude15:11:36

I have experienced that people don't find this obviously better - e.g. read the tweet I linked in the original post

Alex Miller (Clojure team)15:11:59

that person is wrong /shrug

Alex Miller (Clojure team)15:11:35

Clojure embraces nil punning and logical truth values for seqs

clj 1
borkdude15:11:57

the clojure shibboleth :)

Alex Miller (Clojure team)15:11:05

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)

borkdude15:11:50

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? ...))

Alex Miller (Clojure team)15:11:12

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

Alex Miller (Clojure team)15:11:39

and those are cases where I would call (not (empty? )) or (= 0 (count x))

borkdude15:11:03

or (zero? (count x))?

Alex Miller (Clojure team)15:11:18

zero? is actually optimized so that's better

borkdude15:11:24

hmyeah, so it's a bit nuanced

Alex Miller (Clojure team)15:11:34

or I would use empty? and flip the cases

Alex Miller (Clojure team)15:11:15

I think empty? is semantically the cleanest thing to say for a collection

borkdude15:11:51

(if (empty? ...) x y)