There is a mechanism in some lisps where functions can be
given "advice". Allegro CL has this, but it has been deprecated
in favor of "wrapping", a mechanism that works better
with lexical scope and tracing. Documentation is on franz.com.
I don't know if there is anything in GCL exactly like it,
but a free version of "advise" should be around.
For example
(defun foo(x)(1+ x))
(def-fwrapper foo-wrap(x)
(if (oddp x)(+ 100 x) (call-next-fwrapper)))
(fwrap 'foo 'wrapper_1 'foo-wrap) ;; 'wrapper_1 is an made-up ID name for this.
(foo 3) ==> 103
(foo 2) ==> 3
So any function can be intercepted, arguments changed, ...
this way. If it is done cleanly, the function objects will still
work, e.g. #'foo compiled in, will call the wrapped foo, not
the earlier one [mset-save in your example].
fwrap can be used to combine functions in lots of ways. (tellsimp, tellsimpafter,
equivalent, but also other mixtures.)
Should this mechanism be used? In its favor, there is a uniformitiy
argument.
Against it are these thoughts:
Your approach adds overhead to every call to (say) simplifya, to
check for a special case. The "optimal patch" strategy would be
to do what tellsimp does... when simplifya looks at the CAAR of
the expression, it knows what it is working on, and goes to the
property list of the operator to get the simplification program there.
Similar dispatches are done in displa (or nformat), tex, meval, already.
So the right way to make those patches is to look on a property list.
and that is what we should do with mset, too.
e.g.
for each operator foo, one could have an mset property. Then
foo(a,b,c): ..... could be evaluated by being sent to the
function stored on foo's property list under the mset indicator.
This actually makes sense by analogy with common lisp's defsetf.
I think that if there are other plausible programs to modify, they
too should use this kind of dispatch, unless it can really be
shown not to work.
Now that I think of
it, maybe I should rewrite mset that way.
(it might also be ok to rewrite this so it is more accessible
from the maxima language. e.g. use mget instead of get, and
names that start with $. )
.............
I initially thought of mset as a kind of special situation because
I was expecting to have to deal with non-eval'd first argument.
But that is in msetq only, and mset is kind of ordinary as
a lisp function, so I had not followed the thought (and
Stavros' suggestion of table-driven dispatch) to
its logical conclusion, which is consistent with the rewrite
idea above.
RJF
Robert Dodier wrote:
> richard,
>
> i'm very much in favor of implementing defstruct and extending
> mset to handle structures and multiple assignment.
> however i have some quibbles about the code.
>
>
>>(defparameter mset_extension_operators ;; make MLIST acceptable on LHS of assign.
>> (cons (cons 'mlist '$mlistassign) mset_extension_operators))
>
>
> quibble #1. i'd rather steer away from a hook mechanism of this kind.
> potentially any function could be modified. are we going to have a hook
> for every function? that's a mess. how about only the most popular ones?
> displa, meval, simplifya? as soon as we make a list, someone will
> want another function. and even if there are only 6 or 12 functions
> on the list, establishing and maintaining their hooks is still a mess.
>
> won't something like
> (let ((mset-save (symbol-function mset))) (defun mset (xx yy)
> (if (looks like i can handle it) (do my new thing) (funcall mset-save xx yy))))
> work just as well, and much more simply ??
>
> quibble #2. msethack.lisp calls the new assignment function after
> attempting to assign it with the built-in mset. i think we want it to
> work the other way around -- call the new mset first, punt to built-in
> if new mset can't handle it. (and the scheme presented above
> does just that.)
>
> thanks for working on this problem,
> robert dodier
>
> _______________________________________________
> Maxima mailing list
> Maxima@www.math.utexas.edu
> http://www.math.utexas.edu/mailman/listinfo/maxima