Fork me on GitHub
#speculative2019-01-11
>
borkdude18:01:31

today the contract for sequence functions is seqable? to seqable?, whether map returns () or nil is not something you should be thinking about

borkdude18:01:45

any opinions on this @mfikes or @slipset?

Andreas Liljeqvist18:01:45

(if (map a-fn coll) (do-something) (do-else))

mfikes18:01:29

Of the top of my head, I’ve thought map returns (s/nilable seq?)

Andreas Liljeqvist18:01:01

That is correct, it is part of a contract though? - yeah minus nil

mfikes18:01:19

Actually, perhaps nix the nilable part

borkdude18:01:35

that’s the question. also: should we consider different return specs for different seq functions, or treat them under the same contract

mfikes18:01:58

Is the rough idea seqable? in, seq? out?

borkdude18:01:01

@mfikes given that () or nil may be treated as the same value (punning), the question is: is this important enough to spec differently

mfikes18:01:33

Trying to think of things that might return nil

Andreas Liljeqvist19:01:30

map, remove, filter can't return nil - I think it is a bug to write code that relies on them returning nil. If that changes in the future, so will your execution

borkdude19:01:32

you are turning things around: you should not rely on them to return () instead of nil, that should be un-important

borkdude19:01:49

since empty seqs can be nil-punned

borkdude19:01:16

so you should not rely on them returning a more specific value than seqable?

Andreas Liljeqvist19:01:57

there are no such things as empty seqs

Andreas Liljeqvist19:01:25

isn't that an emptylist?

borkdude19:01:02

(seq? '()) ;; true

Andreas Liljeqvist19:01:38

anyhow, I am attacking this mostly from ide tooling angle. I would like to be able to mark code doing (if) on the return of a map as incorrect

borkdude19:01:30

Another example where this is relevant:

(re-seq #"\w+" "")
According to the docs it should return a lazy seq. It returns nil. This should not be regarded as important, since nil and () can be used interchangeably.

Andreas Liljeqvist19:01:02

Yes, but what if that changes in the next version of Clojure, so that nil isn't possible anymore? Nil punning on that stops working. That should probably have an effect on the spec then

borkdude19:01:33

You are again turning it around. You should never nil pun on a result of a sequence function…

Andreas Liljeqvist19:01:07

Yes, and we can have tools that helps with enforcing that

borkdude19:01:55

Sure, but those tools should be able to leverage seqable? and nothing more than that

Andreas Liljeqvist19:01:52

is (when (re-seq ...)) a bug?

borkdude19:01:50

depends. you should call seq on it if you want to confirm if it’s non-emty

borkdude19:01:18

it’s irrelevant if it returns nil or an empty seq when it didn’t find anything

Andreas Liljeqvist19:01:33

interesting, got any example for re-seq returning an empty-seq instead of a nil?

borkdude19:01:58

that should not matter

borkdude19:01:19

you’re not supposed to look at the implementation and then figure out that it’s never going to

borkdude19:01:47

@andreas862 as @alexmiller pointed out, you should always call seq on a sequence if used as a truthy value

Andreas Liljeqvist19:01:35

Sure, but that is why my tooling should mark the bare if-statement

borkdude19:01:35

Another example where you shouldn’t rely on seq? “Returns a sequence of values”

(vals nil) ;;=> nil
(vals {}) ;;=> nil
Same for keys.

Andreas Liljeqvist19:01:04

My argument has always been about the ones that I classified as not nil-punnable. map, filter, remove etc. I did know about some others returning nil

Andreas Liljeqvist19:01:32

But have to say that I do probably use some nil return directly

Andreas Liljeqvist19:01:39

have a lot of code to fix

Andreas Liljeqvist19:01:17

probably re-seq, not sure about the rest

borkdude19:01:07

you were depending on re-seq being able to return nil, despite the docstring?

borkdude19:01:44

I think in that case you should use re-find

borkdude19:01:56

if you want to check if there is at least one match

Andreas Liljeqvist19:01:05

not that sure about re-seq, have to check. But there is a big risk that I would use one of them if I found that it seemed to leave nil for empty.

borkdude20:01:09

We already discussed this in the very start of speculative: https://github.com/borkdude/speculative/issues/45 That’s why we made it seqable? in the first place. Sorry I forgot about this @andreas862. Should have remembered when I merged the change.

Andreas Liljeqvist20:01:12

a non-nil seqable isn't invalidated by that issue.

Andreas Liljeqvist20:01:23

seq? goes out the door though

borkdude21:01:52

For now I reverted back to #45. Any changes to this we should discuss in that issue or at least keep the most important notes there, so we can fall back on that.