| Yes, but Common Lisp is also "stupid dynamic"! I don't think there's anything Python can do that Common Lisp can't in terms of dynamic-ness! This is a quote from python.org: >These languages are close to Python in their dynamic semantics, but so different in their approach to syntax that a comparison becomes almost a religious argument: is Lisp's lack of syntax an advantage or a disadvantage? It should be noted that Python has introspective capabilities similar to those of Lisp, and Python programs can construct and execute program fragments on the fly. Usually, real-world properties are decisive: Common Lisp is big (in every sense), and the Scheme world is fragmented between many incompatible versions, where Python has a single, free, compact implementation. https://www.python.org/doc/essays/comparisons/ I believe there are dynamic things Common Lisp can do that python can't, like modifying and creating classes, inheritance and methods at runtime, even with effects propagating out to already existing class instances! |
I believe there are areas of CLOS which are stupid dynamic; but even there, the specification tries to tread carefully. Firstly, you don't have to use CLOS in a Lisp program; and if you need data structures with named slots, structs may suffice.
Importantly, Common Lisp keeps a kind of basic type versus class type separation in the language. You don't feel it because it's not obnoxious, like int versus Integer in Java. Built in basic object types like integers and strings all have a CLOS class in Common Lisp. But, the class of that class (the metaclass) is not the same as that of a class which the application defines with defclass. The Lisp compiler doesn't have to worry about silly monkey patching being perpetrated on a string or integer.
In some areas of the language, it's clear that the designers were trying to avoid bringing in dynamic behavior that would interfere with performance. For instance, conditions are defined in such a way that they are "class-like" objects, but without the actual requirement that they be CLOS instances.
The meta-object protocol (MOP) was also kept out of the language. I'm not sure whether the MOP is "stupid dynamic" because it also seems to hold the keys to avoiding "stupid dynamic" in that if you don't like some particular dynamism in a given class, maybe you can design your own meta-class which avoids it. It might be possible using MOP to, say, have an object system where the inherited slots of a derived class are at the same offset in the underlying vector storage as in the parent class, so accesses can be optimized. Maybe you can ban multiple inheritance in that meta-class.