Discussion:
gensym returns non-fresh symbols and sometimes integers
(too old to reply)
Kris Katterjohn
2017-07-23 01:49:46 UTC
Permalink
Raw Message
Hey everyone,

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 ("");
(%o1) 117

(%i2) integerp (%);
(%o2) true

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);
(%o4) unknown

(%i5) is (gensym () > 0);
(%o5) true

(%i6) is (gensym () > 0);
(%o6) unknown

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))
T

Ugh.

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
containing them?

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.

Thoughts?

Cheers,
Kris Katterjohn
Robert Dodier
2017-07-23 18:49:36 UTC
Permalink
Raw Message
Post by Kris Katterjohn
gensym uses GENSYM to create a symbol, but this symbol passes through
DOLLARIFY before being returned. This means that gensym can return an
Well, maybe it's enough to paste on the dollar sign before calling
GENSYM.

In that case it's still possible to get something that is a symbol but
looks like a number when it's displayed, something internally like
$1234. I don't see a reason to disallow that -- you get what you asked
for. It's already possible to create such symbols via \1234.

About interned vs uninterned symbols, since the distinction doesn't
exist in Maxima, my advice is to return only interned symbols, as gensym
does now.

best,

Robert Dodier
Kris Katterjohn
2017-07-23 20:35:14 UTC
Permalink
Raw Message
Post by Robert Dodier
Post by Kris Katterjohn
gensym uses GENSYM to create a symbol, but this symbol passes through
DOLLARIFY before being returned. This means that gensym can return an
Well, maybe it's enough to paste on the dollar sign before calling
GENSYM.
OK. That's what my patch does and it seems to work fine.
Post by Robert Dodier
In that case it's still possible to get something that is a symbol but
looks like a number when it's displayed, something internally like
$1234. I don't see a reason to disallow that -- you get what you asked
for. It's already possible to create such symbols via \1234.
Yeah, I have no problem with this being allowed.

I mentioned it toward the end of my (admittedly long) post to say that
allowing symbols that print the same as numbers and allowing uninterned
symbols can both cause the same sort of confusion (where they may look
like one thing, but they're really something else). It's just that you
can type in the name to get the former but not the latter.
Post by Robert Dodier
About interned vs uninterned symbols, since the distinction doesn't
exist in Maxima, my advice is to return only interned symbols, as gensym
does now.
Yeah, that may be the "safer" option, but unfortunately those issues
caused by the interning really seem to limit the usefulness of gensym.

With interning, gensym can make no claims or promises about the symbol
it returns. It just returns some symbol that may or may not have been
used before. I think the name "gensym" and the documentation for it are
misleading.

Thanks for your comments.

Cheers,
Kris Katterjohn

Loading...