Complicated objects in Maxima



Robert Dodier <robert.dodier at gmail.com> wrote:

   On 2012-05-18, Steve Haflich <smh at franz.com> wrote:
   
   > It is an interesting question whether, had generic functions and a
   > discriminable and extensible class lattice existed in Lisp 40+ years
   > ago, whether this would have been useful to the internal protocols of
   > Ma[xi,csy]ma because each subexpression could be minutely subclassed
   > about all it's internal propertes.  That question is arguably still
   > intellectually interesting, but alas any answer to that question is not
   > relevant to current work on Maxima.
   
   Hmm, that sounds interesting. How would that work? What is an example?
   
In way of preface, let me emphasize that I'm engaged in wild blue-sky
speculation.

Formula and equations (let's call them both "expressions") are typically
internalized and manupulated as cons trees with extra annotations
inserted here or there.

Suppose instead each node of an expression (and recursively
subexpressions) were represented as an instance of the standard-class
"expression".  This by itself isn't too interesting and probably
contributes only inefficiency.

One of the main powers of object classes with multiple inheritance is
that behavior can be inherited from multiple superclasses, and extended,
modified, or overridden in various sophisticated ways.  When programmers
think about instances of classes, usually the class of each instance has
been defined by some defclass form explicitly coded by the programmer in
some source file that gets compiled as part of the build.  Existing
stream implementations have superclasses such as input-stream,
output-stream, bidirectional-stream, file-stream, socket-stream, etc.,
with all the necessary combinations defined by defclass directly in the
source code.

But the MetaObject Protocol allows the creation. manipulation, and
combination of classes themselves to be performed programmatically.
Suppose one defined numerous possible classes representing properties of
(sub)expressions.  Each instance of a subexpression would, of couse, be
an instance of expression, but it would also be an instance of a
(mixin?) class that carries a property such as "constant", "monotonic",
"commutative", "nonnegative", etc. etc.  When code asks a question about
a node, the answer becomes class based.  If the subexpression node
doesn't yet know the answer, it can compute it lazily (perhaps caching
the result) but when properties of the subextression are determined (or
declared, or provided by the meatware connected to the CAS system) the
_class_ of the subexpression can be changed, e.g. by cl:change-class.
If that specific combination of superclasses has not yet been defined,
the MOP allows it to defined o the fly, and everything just keeps
working.  Anonymous classes don't even need to be named (e.g. for
retrieval by cl:find-class) although informative names would be helpful
during debugging.

Under such a regimen, an operation that simplifies an expression that is
the addition of two subexpressions would become a generic operation that
uses the classes of its argument subexpression, and what is known about
itself as represented by its own class.

Remember, I don't propose this seriously.  Just something to ponder when
you don't feel like doing useful work.