Of all the features usually attributed to Lisp, by far the most distinguishing is it’s unique sort of homoiconicity. The language itself is represented in the same syntax as its chief datastructure (the singly linked list,) and is in fact parsed into that datastructure for pre-processing before it is actually compiled or interpreted.1 This feature allows Lisp code to be manipulated programmatically far more easily than most programming languages. Usually, this is used to extend the language through Lisp macros, but I wonder why it isn’t more often used to enable better editors and IDEs.
To give you an example of what I mean, take your typical IDE for a typical language, like Eclipse for Java. Among other things, Eclipse has an elaborate Java code parser which it uses to perform complex refactoring operations, such as renaming variables, functions, etc, or intelligently moving code around. Most Lisp editors lack these features. People who write Lisp code will often say that Lisp has less need of automated refactoring tools than Java, which is true, but is also silly, because refactoring tools for Lisp should be really easy to write. The hard part of writing a syntax parser is trivialized by Lisp’s syntax.
That’s just one example. Other things that Lisp syntax should enable in editors are true structural editing, where the editor can treat the code as a tree structure rather than a stream of characters, obviating syntax errors altogether. Static code analysis, looking for obvious bugs, logic flaws, or inefficiencies is another. On the fly regression testing, code completion/generation, better visualizations, code folding, etc all could be possible with a good editor/IDE, and much more easily with a Lisp than another kind of language.2
Anyway, I thought a lot of this stuff would be cool, so I’ve started a bit of an experiment. Tactile is a mostly true structural Emacs Lisp code editor (in Emacs, of course.) Now Emacs already has a number of features to allow structural editing of Lisps, including it’s built in s-exp navigation commands, and the paredit library which not only keeps parentheses (and other paired syntax features, like brackets) balanced, but provides commands which make easier to edit s-expressions. None of this however gets quite to where I want to go. Tactile, contrariwise, parses Lisp code and keeps actual track of the structure of the buffer. It knows where forms begin and end and can operate on code by atom or by form rather than by line, which is an improvement. The end goal is to create an editor which maintains perfect structural integrity in the code. That is, not only will it auto-balance parentheses, it will make it impossible to unbalance them, or to break a string, and it will auto pretty print your code as you type, hopefully unobtrusively.3 Furthermore, it will auto-complete, refactor, auto-generate, and (eventually) statically analyze code. It should be pretty cool.
For now however, Tactile is still experimental, and doesn’t include most of the hoped for features. It’s possibly a step up from standard Emacs+Paredit, in that it selects it’s active member and operates on it in a more ‘tactile’ fashion,4 but it doesn’t do much more than that, yet. Also, it only currently works with Emacs Lisp; my ultimate goes is for it to support multiple Lisp grammars, so Common Lisp, Scheme, and Clojure would all work to, but Emacs is simpler and more available. It doesn’t interact well with Viper-Mode. Also, it’s new, so it may be buggy. Despite all this, I’m still hopeful that this will turn into something useful, so I’m sharing early. The ReadMe is in the code repository, so if you want to try it, go ahead and download it and give it a shot.
- Lisps of all sorts can come in compiled or interpreted variations. ↩
- Actually, with Lisp, you generally also have the advantage of a running instance of the program you’re developing, so static analysis can usually give way to simply interacting with the Lisp instance. Structural understanding of the language still helps though because it let’s you map the feedback from the instance to certain forms in the code. ↩
- :D ↩
- Hence the name. ↩