Fork me on GitHub

@cfleming getting this strange behaviour, and wondered if I'm missing something obvious


Has anyone seen this before?


Not that I’m aware of, I’ll try to reproduce it. Is this CLJ, CLJS or CLJC?


just plain old clj


I can reproduce it.


same code, same error message


it seems to be require specific - other functions (e.g. println, count) don't cause the error


@cfleming did you try this out yet? The issue isn't really affecting me massively, but I am curious about it.


@UCQV87CN7 No, I’ve been off work for a couple of days but I’ll look at this when I’m back.


No worries, thanks.


@UCQV87CN7 So this is just a common or garden variety bug, although it’s a tricky one. require was one of the first forms I added support for (along with all the other ns-related stuff), and since the ns form is so complicated I cribbed a bunch of code for parsing it from tools.namespace, including this:


Much of this code never got retrofitted to use my grammar parsing stuff which would have caught this. So this is still using old parsing code, which tries to parse the forms passed to require as a libspec and decides (due to that check) that it’s a prefix form.


So when a form is a prefix form, the initial symbols will sometimes but not always refer to namespaces. If you have (require '(clojure string (java io))) for example, there’s actually no namespace called clojure anywhere, so Cursive marks that symbol as something that shouldn’t be resolved, since in an actual prefix forms that’s often valid. Obviously, no namespace called -> exists 🙂


Then, since that symbol is marked as not resolving to anything, when Cursive is trying to figure out the arity that’s being used for string/split it looks at the parent list to see if it’s a threading form. But the head symbol doesn’t resolve to anything, so it can’t be, which is why Cursive thinks it’s not in a threading form when it actually is.


The moral of the story is, as I have been preaching but obviously not entirely practising, is to always use grammars to parse your forms rather than ad-hoc parsing like this.


(even when that ad-hoc parsing comes from something battle-tested like tools.namespace)


Wow, that's quite a journey. Thanks very much for the explanation, it's very interesting, and I've learnt a lot from it.