3 ms·
Basically because Common Lisp (along with Smalltalk and very few other languages) is designed from the ground up to support livecoding as its primary workflow.
by mikelevins 5y ago
Basically because Common Lisp (along with Smalltalk and very few other languages) is designed from the ground up to support livecoding as its primary workflow.
The basic idea is that you start up your Lisp and it's already a working program; it just isn't the one you want to make. So you teach it interactively, a piece at a time, how to be the program you want. The workflow is less like constructing something according to a plan, and more like painting a picture or writing a document, looking at what you've got so far and making improvements and corrections as you go, all while the program continues to run. When the running program is what you want, you save it and ship it.
The ANSI Common Lisp standard defines and standardizes a collection of features designed specifically to support this workflow. Because these features are in the standard, you can count on having them in any conforming implementation.
For example, it defines a suite of language features that enable the runtime to automatically detect when you change the definition of a class, and it can automatically reinitialize existing instances to conform to the new definition. If you're not livecoding, those features make no sense; if you are, they are a godsend.
It defines a suite of error-handling features that ensure that a conforming Common Lisp implementation responds to a runtime error by creating an interactive repl known as a *breakloop* that exists in the dynamic environment where the error occurred, before the stack has been unwound, and which provides interactive features you can use to explore that environment, edit it, redefine any values, types, functions or methods, including the ones that are pending on the stack, and then resume execution as if your new definitions had been in place to begin with.
It makes absolutely everything in the runtime environment easily visible to the programmer and places it all under program control, so that you can inspect, edit, and redefine every aspect of the development environment while your work-in-progress is running, and see the effects of your changes instantly.
Those are all common features provided for by the language standard. In addition, there are other conveniences for interactive programming, such as featureful interactive editors and image saving, that are not standarized, but that are sufficiently common in the shared history of Lisp implementations that they are notable when they're absent.
These kinds of features are designed to facilitate working on a living program, modifying it interactively while it continues to run. They enable you to redefine every aspect of the program without ever being required to restart or rebuild it. Of course, that's a lot of power, and sometimes you'll get yourself into trouble with it, but the tools are designed to help you dig yourself back out, or to restart, if you must, from a convenient starting place.
I have about as much experience with Scheme as with Common Lisp. I've been using both since the late 1980s, and have shipped multiple applications and systems with both. I like Scheme. It has some particular features and conventions that I like better than Common Lisp's.
But Common Lisp is what I turn to first, and that's because it's designed around livecoding and Scheme is not.
Some Schemes and similar languages (like early Dylan) have historically provided some of these features. The only Scheme-like language implementation I know of that provided them all was Leibniz, the early Dylan development environment at Apple--and it had them because it was written in Common Lisp and inherited Lisp's features.
Full-featured Smalltalk environments are just as good. Interlisp is just as good (though very dated at this point).
Few other development environments come close.