Awhile back we had some discussion of the merits of writing
packages for Maxima in Lisp or in Maxima. I claim that coding
in Lisp is the best way to avoid name clashes that can plague
Maxima functions that take an argument that is a Maxima
expression. To illustrate:
Consider the function G defined in Maxima as
(C2) G(e,x) := block([z],
z : diff(e,x),
ev(z * e, ratsimp));
(D2) G(e,x):=BLOCK([z],z:DIFF(e,x),EV(z*e,RATSIMP))
Although we declared z to be a local variable, if e depends
on z, we probably don't get what we want:
(C3) G(x*a^8,x);
(D3) a^16*x /* this is what we want */
(C4) G(x*z^8,x);
(D4) x*z^128 /* yikes! this isn't what we want. */
Maxima isn't misbehaving; we have a name clash. We can
avoid the problem by putting a "wart" on the local variable.
For example
(C5) H(e,x) := block([%z],
%z : diff(e,x),
ev(%z * e, ratsimp));
(D5) H(e,x):=BLOCK([%z],%z:DIFF(e,x),EV(%z*e,RATSIMP))
Now we can have e depend on z and H does what we want:
(C6) H(x*a^8,x);
(D6) a^16*x
(C7) H(x*z^8,x);
(D7) x*z^16
Should anyone use a variable %z, we're back to the same problem:
(C8) H(x*%z^8,x);
(D8) %z^128*x
We could tell users not to use warted variables, but as far as
I know, Maxima has no such prohibition. Some commercial Macsyma
code has warted variables (look at the specfun.macsyma code).
I claim that a better way to avoid name clashes is to code in Lisp.
Defining f as
(defun $f (e x)
(let ((z ($diff e x)))
(mfuncall '$ev (mul* e z) '$ratsimp)))
we don't have a name clash because of the way Maxima "dollarifies"
Maxima variables. Thus
(C10) F(x*a^8,x);
(D10) a^16*x
(C11) F(x*z^8,x);
(D11) x*z^16
(C12) F(x*%z^8,x);
(D12) %z^16*x
At least, this is how I see it; spending several evenings with
a good Common Lisp book was the best thing I did for my
Maxima competence.
How do the other M's avoid name clashes?
Barton