name clashes in Maxima



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