Fork me on GitHub
#cursive
<
2017-07-20
>
cfleming01:07:15

@mfikes Thanks, I’m interested to know if it’s any better, or at least not worse, and if the completion etc is noticeably worse.

mfikes01:07:16

I’m running your beta version. Will let you know. Hah, I actually realized I needed to upgrade my Cursive license. I actually had license number 6. 😀

mfikes01:07:34

(Meaning the 6th license you sold.)

cfleming01:07:44

That’s some fast work.

mfikes01:07:41

FWIW, I’ve started using “hippie” completion in IntelliJ, where it simply cycles through directly-entered textual completions, rather than popping up the little completion GUI. It seems to give slightly different results, but I like it.

cfleming01:07:21

It’s probably useful for CLJS I guess, where the interop completion is still not so useful.

cfleming01:07:56

I’m going to add type inference soon, so hopefully that will make it much more useful in the presence of mild annotation (like the new auto externs stuff)

mfikes01:07:36

Cool! It will be interesting to see how Cursive type inference compares to what exists internally in the ClojureScript compiler.

cfleming01:07:19

Right, with all the new Node stuff I should be able to take advantage of the DefinitelyTyped stuff that Typescript uses too.

cfleming01:07:34

That would probably help React Native apps a lot.

mfikes01:07:36

If Cursive starts with simple things like marking the string in (+ 2 "a") that will be amazing 🙂

cfleming01:07:06

Is + hinted to only accept a number?

mfikes01:07:34

The macro is, in ClojureScript. It has meta, I believe, something like ::ana/numeric

cfleming01:07:42

I think CLJS supports JSDoc hints, right? But I don’t see them being used at all.

mfikes01:07:22

I think those were suggested a few years ago, perhaps related to some stuff that Closure could help with

cfleming01:07:02

Right, the wiki page makes it sound like it’s a thing, but I couldn’t find any examples in the CLJS project itself (which is where I would have expected them).

mfikes01:07:12

Even if Cursive had a roughly equivalent type inference engine matching what ClojureScript has, it would be nice to see it statically doing it in the UI.

cfleming01:07:46

Yes, that works well for Clojure, although there’s a lot more I could do with it. It’s mostly used for completion right now, not for inspections.

cfleming01:07:25

But it’s possible to catch things like (instance? x String) now, which would help me a lot - I always get that wrong.

mfikes01:07:32

Here is the bit that essentially means “this operation works on numbers” so that that ClojureScript compiler can detect type mismatches: https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/core.cljc#L1021

cfleming01:07:37

But that’s only typing the result, not the params, right?

mfikes01:07:48

It is the params being constrained

cfleming01:07:12

Does that also constrain the result type?

mfikes01:07:27

(It is not a normal type hint, but a mechanism the analyzer uses to emit :invalid-arithmetic warnings)

mfikes01:07:47

The one place where result types are heavily type-hinted is ^boolean

cfleming01:07:50

Ok, interesting - I should be able to use that, yes.

cfleming01:07:02

Right, because of the truthiness performance.

mfikes01:07:09

(This is so that it can do unchecked if evaluations`)

mfikes01:07:20

The recent addition on master to check types passed to aget and aset is essentially custom code inside the analyzer that has been hard-coded to know what those core functions accept.

cfleming01:07:02

Right. dnolen was actually talking about using spec for the CLJS project, but I suspect that’s a long-term goal.

cfleming01:07:55

So the arithmetic warnings are actually produced by the CLJS compiler? Or does it create hints which allow Closure to catch them?

mfikes01:07:05

Yes, if s/fdef was being used, the analyzer could probably detect a lot of stuff statically 🙂

mfikes01:07:27

Right, the arithmetic warnings are generated when it looks at the AST.

mfikes01:07:37

(It is in the analyzer part of the compiler)

mfikes01:07:23

Here is the point where the analyzer is looking at the js* special form that + expands to, and doing arithmetic type checks: https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L3026

mfikes01:07:05

That essentially results in type checks for macros, and recently this was added that allows a similar thing to be done for functions: https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L3467-L3479

mfikes01:07:57

The salient aspect is that it is all being done by looking at the inferred types in the AST and checking to see if function invokes are valid given things that mark what those functions require.

cfleming02:07:33

And that’s a static check during compilation, right?

cfleming02:07:52

What happens when the compiler doesn’t have enough information?

mfikes02:07:03

The cool thing is the type inference is in there (it knows what the types are, if it can infer them). The uncool thing is it doesn’t know what parameters need to be. That will take spec, I guess.

cfleming02:07:28

i.e. (defn foo [arr elem] (aget arr elem))

mfikes02:07:35

Yes, it is done during the analysis phase of compilation. It has to be conservative and not emit diagnostics if there is not enough informatino.

cfleming02:07:22

The tricky part about type inference is that it’s much more powerful if you infer function param types from call sites, but it’s difficult to do that in a performant way.

mfikes02:07:52

Right, in that example, arr and elem are of type 'any and will be assumed to be valid arrays, via this bit here https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/analyzer.cljc#L2998

cfleming02:07:17

Ah, I see - interesting, thanks.

mfikes02:07:52

Yeah, so it only catches gross type mismatches. It is very easy to have code where you can say nothing about its correctness.

cfleming02:07:19

Actually, I saw the other day that it looks like there are some clj-* type tags too, but I couldn’t find any examples of them. Do you know what they’re about?

mfikes02:07:05

I’ve seen clj-nil but I haven’t gained an appreciation for what it is really

cfleming02:07:33

I can’t find the code now

cfleming02:07:50

Looks like clj clj-or-nil clj-nil

mfikes02:07:54

Hah, even some rudimentary checks would be nice. It is surprising how often code is committed that has calls with incorrect arity. A common example is (ex-info "hello"), which no Cursive user would commit. 🙂

cfleming02:07:18

Yes, the arity checking was a huge bang for the buck.

erichmond02:07:24

I had license 85, and I thought I was hot stuff @mfikes 😂

cfleming08:07:43

For those of you using parinfer, there’s a new demo up of a new Smart Mode, which will hopefully replace the Indent/Paren mode distinction. Please try it out and let us know what you think: https://shaunlebron.github.io/parinfer/demo

cfleming08:07:04

cc @puzzler, I know you were interested in this: ^^

cfleming08:07:00

I’m hoping to get this into a Cursive dev build soon so I can try it for real work, but it seems very promising. There are a few edge cases to investigate, but it’s looking very nice IMO.