Hacker News new | ask | show | jobs
by jimws 2393 days ago
Lisp had this kind of interactive programming support for a long time using SLIME and Emacs. Why isn't this a more common feature in the more recent languages?
5 comments

There are two aspects here: Interactive Development is incredible difficult. There is a talk of Anders Heijlsberg about that compiler building is no longer the same than 10 years ago. When you code, you need sub-100-ms reactions, the parser needs to be happy parsing incomplete, typically errorous code and then you need a code analysis engine dealing with that half-baked AST. Also traditional compilers are a strict pipeline and not a loop etc. Microsoft had to rewrite the C# compiler for that. The PHP LSP had to create an own parser engine because no suitable was available. It is essentially a lecture for future language creator: If you write a compiler, do not only built it for binary emitting but also for editors and analyzers.

And yes, the smart-asses of the 70/80s (aka LISP and Smalltalk) thought about that long time before anyone else. But hey, today's landscape is a bit more complex (think about CSS styles in a HTML embedded in a TypeScript enriched JavaScript JSX file).

The second aspect: LSP is great because it was a cross-vendor, cross-language initiative which had in its first year already two dozen languages on board in addition to half a dozen editors (VS Code, Emacs, Atom, VIM, ...). Emacs plugins could never deliver that because they were bound to Emacs.

RE the second aspect: that's why I'm a fan of LSP and the related debugging server protocol. There's no way Emacs can have native IDE-like support for all the languages out there, and the small developer base makes it hard to compete with IDEs for popular languages, that have commercial interests backing them. LSP promises to level the playing field - it only takes one good language server to make IDE features suddenly available not just for IDEs, but also Emacs and Vim and others.
For that matter, VB, C#, Java and even Delphi all had a RAD approach to developing UIs. Why don't more modern languages work on even a basic UI as part of their standard libraries. What kind of system doesn't have a UI these days? Outside of servers obviously. The closest Go and Rust (modern languages...) are getting to a UI seems to be WebAssembly, which for now points towards an Electron UI solution.

I'm not super familiar with SLIME, but that's the goals of LangServ is to consolidate everything into a known protocol. There's also a spec for debugging.

Oddly enough the Wikipedia page for SLIME doesn't seem to mention Racket[0], but it does mention Clojure.

[0]: https://en.wikipedia.org/wiki/SLIME

A flexible UI library that is up to modern expectations is complex and hard. It is even harder if it is supposed to be cross platform. So the only realistic option is to bind to a good existing library. However, these are all written in C++ and hard to bind to anything else. Gtk isn't sufficiently cross-platform to be attractive.

In the end, this is a project that is at least as much effort a creating a programming language.

And here are UWP Apps. They are based on a vNext edition of COM and use language projections to enable a OO-style usage in C#, JavaScript, C++. Actually works. In the end you work in the languages with these objects like any other object in that language.

It is possible, just require major engineering smartness (like writing and improving compilers, code generation, etc).

Hell, it doesn't even have to be ultra advanced. Something close enough to Tk (not GTK, but Tcl/Tk which gets used by Python and a few other languages) would be fine in my book. It is simple, and a start, and allows the community to derive from a working solution to form amazing alternatives.

In fact... Racket has their own UI approach, but I'm not sure if it's just GTK under the hood or what, but it works cross platform.

You're pretty much making my point for me, aren't you? UWP is a single platform interface only and the development of the bindings has taken a tremendous amount of work, as you say yourself.

Projects like sip and PySide show how much effort it takes to make Qt bindings form Python.

And all of this discussion just the bindings, not the actual widget libraries themselves and the effort that goes into those.

Yepp. It is just a sub point I address. That you can successful translate c++ UI libs into other languages.

But generally, you are right. Language development is expensive enough. UI stack development is in difference to class lib development not a duty of a language developer.

It's actually really common but the problem was that, until recently, it was an IDE specific feature and some of the best IDEs weren't free.

What this article is about is the new(ish) open protocol originally developed for Visual Studio Code that is being adopted by quite a few other editors. The language server protocol (LSP) enables developers to write the kind of tools you're describing and have them support any editor (which has LSP support) on any OS. It's pretty cool. However it's also a fairly involved process writing one so many of the smaller languages haven't yet had the bandwidth to writing their own language servers.

The problem is much easier (at least 10x easier) for a dynamic language with a REPL or playground environment (scratch in Emacs) than it is with a static language, or providing stateless insight based on cursor location rather than the set of forms you've evaluated.

With a REPL or playground, you've got all the libraries loaded, all the function definitions in a map in your interpreter, and if you have a partial identifier you can simply do a prefix search in the interpreter. The interpreter is live; define a new function, and it's added to the map, so it's available for subsequent completions. If the function definition is wrong, hey, it's a REPL, next line try again please.

In a stateless situation, or for a static language, you need to build that map. Ideally you use the compiler's front end, but then the front end needs to be hardened to recover properly from errors. It needs to be told about the cursor location, and when it hits the cursor location in the middle of an incomplete symbol, it needs to figure out what's appropriate to complete at that point based on the stack of scopes available, and jump back out to the editor (or use coroutines, or pause its thread, or whatever) with what it found. It's simply more work. And if you can't use the front end, because the front end wasn't built for it, and you can't modify it, well you're going to have to build what is effectively a new front end to solve the problem.

> Lisp had this kind of interactive programming support for a long time using SLIME and Emacs.

For those like me who have Vim burnt into their fingers and brain, there is Slimv[1] for Vim. Another alternative is Vlime[2] for Vim. Both these plugins are based on the same client-server architecture that SLIME is based on. In fact, these plugins rely on Swank TCP server (the same thing that SLIME also relies on). Swank receives SLIME commands from Slimv or Vlime and executes them. Of these two Vim plugins, I prefer Slimv personally because apart from supporting Common Lisp, it supports MIT Scheme and Clojure too. Vlime supports Common Lisp only at this time.

[1]: https://github.com/kovisoft/slimv

[2]: https://github.com/l04m33/vlime

Or Spacemacs with Slime.