Hacker News new | ask | show | jobs
by Jare 3383 days ago
To clarify: do you think there are sets of semantic decisions using S-expressions that would still "get rid of the whole debate", and not make autocomplete harder in practice?

(not that it's important of course, but your remark made me curious, and the reactions to my question even more so)

1 comments

Autocomplete is most commonly used on structures in order to find out which fields and methods that structure contains.

If you used an s-expression based grammar that still had fields and methods, then you'd get the exact same experience.

    foo.bar. <- autocomplete here
vs

    (foo.bar.)
            ^ autocomplete here
Except that in some Lisps where you have multi-methods or generated field accessor methods you'd probably would write it backwards. Maybe like this:

    (. (bar foo) ...)
      ^ cursor is here
I develop Cursive, an IDE for Clojure code. I handle this for Java interop in a couple of ways. Cursive does type inference (or propagation, really) in the editor, so if you have enough type hints it knows what the type of a symbol is. This allows a few tricks (| is the caret):

If you've already typed the form and are just changing the head symbol, you're golden:

  (.myMeth| my-object)
If Cursive can accurately determine the type of my-object, you'll only see the relevant completions, i.e. methods from that type.

If you're using Clojure's threading forms, Cursive understands that:

  (-> my-object .myMeth|)
also works.

Otherwise, if you're typing out a new form you can do:

  (my-object .myMeth|)
and when you auto-complete the forms will be switched around to:

  (.myMethod my-object |).
Maybe a stupid question because I don't know much clojure but I'm curious. How can you be sure that -> is threading macro and my-object is what you think it is at compile time? Can't macros change the entire meaning of an expression?
That's not a stupid question at all, and yes they can. Cursive works using static analysis rather than runtime introspection, so I need to teach it how macro forms work. This uses an extension API internally which will eventually be open so that users can add support for their own forms or forms in libs they use. Cursive uses the information about the macro forms to do symbol resolution, so that's currently a best effort in the presence of forms it doesn't understand yet. It works pretty well though since Clojure doesn't tend to use as many macros as, say, Racket. Doing full resolution means that I can distinguish clojure.core/-> from some other symbol with the same short name, it's not just using the -> text.

One correction - this is all done at edit time, not compile time. At compile time there's no issue since all macros are expanded to the core language.

Thank you all for your comments. Swapping the forms is pretty neat!
Sure. That's a property of the language, not S-Expressions.

It's just like how SQL decided to write all their queries backwards making it impossible to do good autocomplete.