On Sat, 2021-03-13 at 14:00 -0800, Diego Sejas wrote:
> Any symbolic ring in Sage has a dictionary called "symbols". (I'll refer
> specifically to "SR" for the following.) "SR.symbols" contains all the
> previously defined variables through "SR.var()" and/or "SR.symbol()".
> However, this generates a problem: Many symbols remain stored there even
> when they have been overwritten for other purposes. For example, when one
> starts a new Sage session, Sage executes the line
>
> from sage.calculus.predefined import x
>
> This is done in order to have "x" as a default predefined symbolic
> variable.
This defines two things; a symbol named "x" that is some kind of python
object, and a python variable "x" that points to the symbol object. The
distinction is important but you're right regardless.
> However, the whole file "sage/calculus/predefined.py" is executed
> which calls "SR.var()" on every single letter of the alphabet (lowercase
> and uppercase). So, when one has a freshly started Sage session (without
> any additional execution), "SR.symbols" already has length 48:
>
> SR.symbols = {'a':a, ...'z':z, 'A':A, ...,'Z':Z}
>
> Since "x" is the only predefined variable, this should be simply
> "SR.symbols={'x':x}".
If anything, that file should be calling SR.symbol on each letter, or
SR.var on the collection of letters. But I agree with your guess on
ask.sagemath that this is a premature optimization and a waste of
startup time/memory in most cases.
>
> An even bigger problem is seen with the following code:
>
> SR.var('foo')
> # Do something meaningful with "foo" until you don't need it anymore
> foo = 2
> # Do something meaningful with the new meaning of "foo"
>
> This keeps "foo" listed as a symbolic variable in "SR.symbols" even though
> it is now an Integer. In time, "SR.symbols" gets cluttered with
> non-existing symbolic variables.
This is okay. The symbol object still exists even though you've
clobbered the name that refers to it. Having "foo" in SR.symbols allows
you to retrieve the underlying symbol object again (keeping its domain
intact, for example) with foo = SR.symbol("foo"). You don't need to use
the variable name "foo" to point to the "foo" symbol object, of course.
If you ever start to feel that programming in sage is too easy, try
defining x = SR.symbol("y") and y = SR.symbol("x").
I say this is "okay" because that's how it's intended to work. Maybe on
average that prevents us from garbage collecting a bunch of names for
symbol objects that will never be referenced again. Who knows.
> Do we really need this behavior? Is it "SR.symbols" necessary at all? Could
> we remove it?
I have no idea why the dictionary is public in the first place. It
looks to me like it should be private, and that you should use
SR.symbol("foo") to retrieve the stored object rather than
SR.symbols["foo"].
And yes we should avoid predefining the entire alphabet.