2017-07-23 01:49:46 UTC
gensym uses GENSYM to create a symbol, but this symbol passes through
DOLLARIFY before being returned. This means that gensym can return an
integer instead of a symbol:
(%i1) gensym ("");
(%i2) integerp (%);
And similarly for gensym("1"), etc.
Also due to DOLLARIFY, when gensym would return a symbol, this symbol
would be interned in the maxima package. So there could be, say, facts
known about Maxima gensyms before they're returned by gensym. This
violates the fact that these symbols should be fresh:
(%i3) assume (g119 > 0)$
(%i4) is (gensym () > 0);
(%i5) is (gensym () > 0);
(%i6) is (gensym () > 0);
I would not expect anything to be known about a (supposedly) brand-new
gensym. Same goes for them already having values, etc.
Another issue (again since the symbol is interned) is that calling
gensym multiple times with the same integer argument just returns the
same symbol each time:
(%i7) :lisp (eq ($gensym 1) ($gensym 1))
I've attached a patch which aims to correct this. With it, gensym will
return a fresh, *uninterned* symbol (but one whose name still begins
with "$"). So these will be honest lisp gensyms.
The test suite runs fine with this.
However, with this change Maxima will be returning something that looks
"normal" but is something that a user cannot type in to access. Maxima
can return expressions that contain gensyms, and right now when using
Maxima interactively you can just type in the name of these gensyms and
things work as you might expect based solely on how it looks:
(%i7) desolve ('diff (f (t), t) = g (t), f (t));
(%o7) f(t) = 'ilt(('laplace(g(t),t,g121)+f(0))/g121,g121,t)
(%i8) subst (x, g121, %);
(%o8) f(t) = 'ilt(('laplace(g(t),t,x)+f(0))/x,x,t)
With this change the gensyms will look like ordinary symbols (i.e.,
there is nothing distinguishing about the way they look other than
they're of the form g<integer> by default), but you will not be able to
just type in their names (of course you can pick them out of expressions
with part or something though).
Interning doesn't fix all issues of confusion. Assuming the behavior
illustrated in %o1 gets fixed, gensym can still return a symbol that
prints the same as a number, although it doesn't do this by default.
The current behavior of gensym is bogus, but perhaps using uninterned
symbols is going too far since Maxima functions can return expressions
Does using uninterned symbols break or prevent anything else?
Maybe the returning-an-integer behavior should be fixed, but gensym
should still return an interned symbol? This is certainly not perfect
since the symbol will still not be fresh and those aforementioned issues
will still remain.