Earlier quoted context omitted.
Speaking as a longtime (nearly 30 years) Common Lisp programmer, I agree with what you've said here, but I would add one thing more. Common Lisp is one of a small number of languages that represent an approach to programming that is so out of fashion nowadays that it seems to be in danger of becoming extinct. The approach is one that treats programming as an exercise in interactively shaping a living thing in real ti…
Interesting comment. I suppose it is along roughly the same lines as Paul Graham's essay about top down vs. bottom up programming (?) Read it a while ago, not handy on mobile right now. What is it about CL / Lisp that makes people think it more suitable than other languages for using in such a style? It cannot be only the REPL, since others have them too. Or are CL REPLs more powerful? I've only explored one a bit, F…
Common Lisp isn't the only language designed that way. Older Lisps were, too. So was Smalltalk. But that view of programming is now so far out of the mainstream that even new Lisp dialects don't reflect it.
But you asked for examples of other Common Lisp functions that take interactive programming into account. Instead I'll offer a mixed list of functions, special forms and design features. Don't assume it's exhaustive; there are too many to reasonably expect that I can list them all.
- COMPILE doesn't mean compile a file; it means compile an arbitrarily chosen function that might not even be in a file anywhere
- EVAL-WHEN enables you to control whether forms are evaluated at compile time, load time, or toplevel-evaluation time, because you might have program text that is intended to be evaluated at any combination of those times. Again, its behavior is independent of whether the affected forms appear in files (though obviously that's the most common place for it to appear).
- namespaces are represented by packages, which are runtime objects that you can interactive inspect and modify. The namespaces represented by packages have a concept of public and private names, but you can't really hide private names, because if you could it would be impossible to change them at runtime. Common Lisp is allergic to features that are impossible to change at runtime. It has to be in order to support interactive programming.
- CLOS has a whole protocol for changing the definitions of classes and functions while a program runs. CHANGE-CLASS and UPDATE-INSTANCE-FOR-REDEFINED-CLASS are members of that protocol. SO are REINITIALIZE-INSTANCE and SHARED-INITIALIZE and UPDATE-INSTANCE-FOR-DIFFERENT-CLASS and ADD-METHOD and REMOVE-METHOD and DEFINE-METHOD-COMBINATION.
- introspection is pervasive in Common Lisp. It has to be. It's an interactive system in which you build programs while they are running. You have to be able to examine every part of the running program as it runs. So it has scads of functions for examining the structure and value of everything in the running program--and not just examining it, but changing it. There's BOUNDP and SLOT-BOUND-P and SLOT-EXISTS-P and FMAKUNBOUND and FIND-METHOD and TYPE-OF and CLASS-OF and SYMBOL-FUNCTION and so on and so forth. DISASSEMBLE, which decompiles compiled code so that you can interactively examine what the compiler produces, is part of the language standard.
- the assumption of interaction is also pervasive. TRACE and INSPET are part of the standard. So is BREAK--a function that causes the program to enter an interactive breakloop in which you can examine the dynamic state of the suspended computation, inspect and change the values of local variables, redefine functions and methods, and resume the interrupted computation when you think you've made the changes you wanted.
- you asked about the condition system. You could say that it's Common Lisp's implementation of exceptions, and that would be true as far as it goes, but it would also ignore important aspects of its design. Yes, you can raise a condition, just as you can raise an exception. However, the normal behavior of an unhandled condition is to drop you into an interactive breakloop from which you can modify the suspended computation and all of its accessible state.Conditions provide restarts -- a mechanism for offering a set of options for resuming control at a place of your choosing, or of selecting how to resume execution under program control. Conditions are also more generally useful as ways to manage nonlocal transfers of control.
- it's not explicitly part of the standard, presumably because it was such a fundamental assumption of Lisp programmers when Common Lisp was being defined, but nearly all Common Lisp implementations support saving a serialized form of the dynamic run-state of the system that can later be reloaded to reproduce that dynamic run-state exactly. It means that you can save the exact environment that you're working in right now, complete with interactive state like breakloops and so forth, and resume it later. You can, for example, discover a bogu, dig into what you can find out by inspecting the dynamic state of a breakloop triggered by the bug, and save off that whole dynamic state, then reload it on another machine so that you can show it to a colleague in all its glory.
There's more, of course. It's hard to reduce a design that is all of a piece to a list of discreet features.